package cn.cihon.ubi.qorosauto.storm;

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;

import java.util.*;
import java.util.Map.Entry;

import cn.cihon.ubi.qorosauto.biz.EconDataGenerator;
import cn.cihon.ubi.qorosauto.bo.LocationInformation;
import cn.cihon.ubi.qorosauto.bo.StatData;
import cn.cihon.ubi.qorosauto.bo.TripData;
import cn.cihon.ubi.qorosauto.bo.VehicleStandardData;
import cn.cihon.ubi.qorosauto.util.DateUtil;
import cn.cihon.ubi.qorosauto.util.MathUtil;
import cn.cihon.ubi.qorosauto.util.ModeArrayList;
import cn.cihon.ubi.qorosauto.util.NightDriving;
import cn.cihon.ubi.qorosauto.util.RushHour;

public class TripCalculateBolt extends BaseRichBolt {

	/*
	 * 用来计算各种形成数据的类，并把trip对象传到下一个Bolt，用来存储
	 */
	private static final long serialVersionUID = 1L;
	public OutputCollector collector;

	// 定义一个包含所有要求指标的hashmap，key为VIN号，value为所有要求指标
	private HashMap<String, TripData> tripDataMap = null;
	
	/*
	 *  以键值对形式存储行车数据。成员变量作用如下：
	 *  1.行程计算开始时系统可以从此map中可以读取当前车辆上一次的行车数据
	 *  2.行程计算结束时系统使用本次产生的行车数据覆盖上一次行车数据，以保证下次计算时可以取得上一次的行车数据
	 */
	private HashMap<String, VehicleStandardData> stdDataMap = null;
	
	/*
	 * 获得上一次行车数据记录时间
	 * 如果是第一次登陆系统的车辆不会有上一次行车记录，直接返回null
	 */
	private Date getLastRecordTimestampByVIN(String vin) {
		VehicleStandardData stdData = stdDataMap.get(vin);
		// 第一次登陆系统的车辆不会有上一次行车记录，直接返回null
		if (stdData == null) {
			return null;
		}
		Date recordTimestamp = stdData.getRecordTimestamp();
		return recordTimestamp;
	}
	
	// 用于计算行车指标众数的变量
	private ModeArrayList mv = null;
	private StatData statData = null;
	private int i = 0;

	/*
	 * 设置变量记录每天处理的数据条数 还有当前在线的车辆数
	 */
	private long numDataProcessed = 0;
	private long numCarOnline = 0;

	int iii=0;
	
	
	/**
	 * The bolt will receive the line from the words file and process it to
	 * Normalize this line
	 * 
	 * The normalize will be put the words in lower case and split the line to
	 * get all words in this
	 */
	public void execute(Tuple input) {

		/**
		 * 行车信息是指一辆车一个行程里某一秒产生的一类数据， 为了保存这一类数据，创建了CarData类。
		 * 从每天0点到24点，一辆车会有多个行程，由于部分数据必须依赖前后两次行程数据进行计算，例如： 计算怠速时间、判断行程开始。
		 * 
		 * 需要缓存某车上一次行程数据，为了方便获取上一次行车数据，将上一次行车数据以HashMap保存，
		 * VIN码为key，上次行程产生的CarData为value。 每次计算结束后要系统要做三件事： 1.将数据推送到redis内存数据库;
		 * 2.将数据保存到文本文件; 3.用本次计算获得的CarData替换HashMap中的值
		 * 
		 * 由于CarData表示一辆车一个行程里某一秒产生的数据，CarData拥有多种状态。
		 * 按行程可以划分为：1.行程开始（前一次行程已经结束后，接收到的第一条数据）；2.行驶中；3. 行程结束（发动机转速为0）。
		 * 
		 * 行程开始的判断依赖于上一次行程结束时点的数据，当新数据来到时，如果HashMap中没有对应车
		 * 辆的数据，就把此数据当做行程开始数据，如果HashMap中有此车对应的数据，而且该数据的行程
		 * 标志为行程结束，此数据也看做行程开始数据。需要注意的是状态为行程开始的数据并非各个指标
		 * 都为0的数据，此时发动机发动、电瓶供电，会产生很多数据。
		 * 
		 * 若不符合上述判断条件，且发动机转速不为0的数据是行程中数据，行程中数据在计算过程中的处理 过程和行程开始数据没有区别。
		 * 
		 * 为了方便实现，此程序以发动机转速为0来断定行程结束，但是这样可能会存在一个问题，就是发动机
		 * 转速为0之后仍然会有连续多秒的发动机转速为0数据，此时不记录这些数据，因为实际上行程已经结束
		 * 了。在行程结束的时候要计算行程指标和打分指标。由于使用了实时运算框架，所以是可以在行程中计算
		 * 行程指标和打分指标的，但是也许这样会消耗很多性能，因此在行程中尽量保存过程数据，避免计算
		 */

		// 从Spout中获取传来的Tuple
		VehicleStandardData stdData = (VehicleStandardData) input.getValue(1);
		
		// 获得tripData对象，先判断VIN号是否是一个新车架号,如果是就用之前的hashmap，如果不是新建自己的hashmap对象
		TripData tripData = getTripDataByVIN(stdData);

		/*
		 * 有效的数据量
		 */
		Long youxiaodeshujuliang = tripData.getYouxiaodeshujuliang() + 1;
		tripData.setYouxiaodeshujuliang(youxiaodeshujuliang);

		// 判断tripFlag标志
		judgeTripFlag(stdData, tripData);
		
		try {
			
			// 根据不同的tripFlag调用不同方法，更新tripData属性值（初始化、更新中间变量、计算最终结果）
			Integer tripFlag = tripData.getTripflag();
			if (tripFlag == TripData.START) {
				// 行程开始时给需要初始化的属性赋值
				kaishi(stdData, tripData);
			} else {
				// 行程中更新中间变量
				zhongjian(stdData, tripData);
				// 行程结束时，计算最终结果
				jieshu(stdData, tripData);
				System.out.println("1.准备emit行程数据，时间为：" + tripData.getRecordTimestamp());
				this.collector.emit(input, new Values(tripData));
			}
			
			
		} catch (Exception e) {
			tripData.setYouxiaodeshujuliang(tripData.getYouxiaodeshujuliang() - 1);
			e.printStackTrace();
		} finally {
			
				//System.out.println(i + ",");
			    i++;

			// 记录已处理的数据条数（按天算）
			//statData.setNumDataProcessed(getNumDataProcessed(statData));

			// 记录当前时刻在线车辆
			//statData.setNumCarOnline(getNumCarOnline(hm));

			// System.out.println("原始数据：" + stdData.toString());
			// System.out.println("绿色行驶评分：" + tripData.getEcoPoint() +
			// ", 安全行驶评分：" + tripData.getSafePoint());
		}
		
		stdDataMap.put(stdData.getVIN(), stdData);
		collector.ack(input);  
	}
	
	private void judgeTripFlag(VehicleStandardData stdData, TripData tripData) {
		Integer tripFlag = tripData.getTripflag();
		Double engineSpeed = stdData.getEngineSpeed();

		if (tripFlag == TripData.END) {
			tripData.setTripflag(TripData.START);
		} else {
			tripData.setTripflag(TripData.DRIVING);
		}
		
		Boolean isFirstOne = isFirstRecordOfTheDay(stdData);
		if (engineSpeed == 0 || isFirstOne) {
			tripData.setTripflag(TripData.END);
		}
	}
	
	/*
	 * 判断TripFlag包括对两类车的判断，一个是传过来的当前车的数据，另一个是其余所有车辆此刻没有数据传过来的判断
	 *	传入的参数为HashMap,然后遍历HashMap，如果当前数据的VIN和HashMap的VIN相同，进行下面方法一的判断，
	 *如果不同，进行下面方法二的判断
	 *
	 *一、对一辆车也就是有数据的车的判断
	 *		 
	 *		判断行程开始的条件： 所得数据行程标志是END
	 * 
	 * 	判断行驶中的条件： 所得数据行程标志不是END
	 * 
	 * 	判断行程结束的条件： 1.车速为0二十分钟 2.0点0分0秒
	 * 	1.1车速为0二十分钟的判断方式：
	 * 		当车速为0时，看延时标志isDelay，如果isDelay==false，设置
	 * 		延时标志为true并设置延时开始时间为当前系统时间;如果isDelay==true，让系统当前时间减去延时
	 * 		开始时间，判断差值是否大于20分钟，如果大于20分钟，设置TripFlag为End并写入文件;如果车速不
	 * 		为0,设置isDelay为false，延时开始时间为0;
	 * 		
	 * 	综上，判断行程状态需要：行程标志，车速，当前时间
	 * 
	 * 二、对其余所有车（也就是此刻没有数据的车的判断）
	 * 	
	 * 		次方法只需要判断是不是TripEnd即可
	 * 			
	 * 			如果TripFlag==End，不进行计算
	 * 
	 * 			如果TripFlag！=End，看延时标志isDelay，如果isDelay==false，设置
	 * 			延时标志为true并设置延时开始时间为当前系统时间;如果isDelay==true，让系统当前时间减去延时
	 * 			开始时间，判断差值是否大于20分钟，如果大于20分钟，设置TripFlag为End并写入文件
	 * 		
	 * 该方法更新传入的tripData的tripFlag值
	
	private void judgeTripFlag(VehicleStandardData stdData,HashMap<String, TripData> hashMap) {
		
		 Iterator<Entry<String, TripData>> iter = hashMap.entrySet().iterator();
		 //遍历hashmap
		 while (iter.hasNext()) 
		 {
		 Map.Entry entry = (Map.Entry) iter.next();
		 Object key = entry.getKey();
		 Boolean isFirstOne = false;
		 Boolean isSpeedingTwenty=false;
		 if(key.equals(stdData.getVIN()) && key!=null)       //当前有数据的车辆VIN传入时
		 {
			 TripData tripData = (TripData)entry.getValue();
			 Integer tripFlag = tripData.getTripflag();

				if (tripFlag == TripData.END) {
					tripData.setTripflag(TripData.START);
				} else {
					tripData.setTripflag(TripData.DRIVING);
				}
				// 判断当前行车数据是否为当日0点0分0秒产生的，或者当日0点0分0秒后产生的第一条数据
				isFirstOne = isFirstRecordOfTheDay(stdData);
				if(stdData.getVehicleSpeed()==0)                  //如果车速为零，判断为零的时间长度
					isSpeedingTwenty= isSpeedingTwentyMinutes(tripData, stdData);
			
				// 当停车延时超过20分钟或时间为一天的开始时
				if ( isSpeedingTwenty|| isFirstOne) {
					tripData.setTripflag(TripData.END);
					// 输出计算结果
				   tripDataDao.storeTofile(tripData);
				}
		 }
		 else                                                 //当前数据传入为null的VIN要进行的操作
		 {
			    TripData tripData = (TripData)entry.getValue();
			    // 判断当前行车数据是否为当日0点0分0秒产生的，或者当日0点0分0秒后产生的第一条数据
				isFirstOne = isFirstRecordOfTheDay(stdData);
				if(tripData.getTripflag()==2){}         //当行车标志为行程结束时
				
				else                                                   //当行车标志不是行程结束时
				{
					isSpeedingTwenty= isSpeedingTwentyMinutes(tripData, stdData);
				    // 当停车延时超过20分钟或时间为一天的开始时
				   if ( isSpeedingTwenty|| isFirstOne) {
					tripData.setTripflag(TripData.END);
					// 行程结束时，计算最终结果
					jieshu(stdData, tripData);
					// 输出计算结果
					tripDataDao.storeTofile(tripData);
				}
		 }
		 }
		 }
		
	} */

	/**
	 * 此方法返回是否速度为零二十分钟
	 * 
	 * 遍历所有行车数据，对所有行程标志非End的车辆进行延时判断
	 *延时标志为true，判断延时时间是否大于20分钟
	 * 延时标志为false，记录延时开始时间
	 * 
	 * 
	 * @param tripData
	 * @param stdData
	 * @return
	 */
	private Boolean isSpeedingTwentyMinutes(TripData tripData,VehicleStandardData stdData) {
		
		Boolean isSpeedingTwenty = false;       //设置是否延时二十分钟的标志
		
		if(tripData.getIsDelay())                           //当进入延迟时间时
		{
			//判断结束时间减去开始延时时间是否大于20分钟（即1200000毫秒）
			if(DateUtil.dateDiff(new Date(), tripData.getZeroSpeedStartTime())==10000 || DateUtil.dateDiff(new Date(), tripData.getZeroSpeedStartTime())>1200000)
				isSpeedingTwenty = true;          //设置延时二十分钟标志为true;
		}
		else
		{
			tripData.setIsDelay(true);                                                       //设置isDelay为true
			tripData.setZeroSpeedStartTime(new Date());                 //设置开始时间为当前系统时间
		}
		
		return isSpeedingTwenty;
	}

	// 判断当前行车数据是否为当日0点0分0秒产生的，或者当日0点0分0秒后产生的第一条数据
	private Boolean isFirstRecordOfTheDay(VehicleStandardData stdData) {
		// 获得上一次行车记录产生时间
		Date lastRecordTimestamp = this.getLastRecordTimestampByVIN(stdData.getVIN());
		// 获得当前行车记录产生时间
		Date recordTimestamp = stdData.getRecordTimestamp();
		// 获得当日开始时间
		NightDriving nd = new NightDriving(recordTimestamp);
		Date startTimeOfTheDay = nd.getStartTimeOfTheDay();
		
		// 判断本次行车记录是否为当日产生的第一条数据，上一次行车记录产生时间 < 当日开始时间 < 当前行车记录产生时间
		Boolean isFirstOne = DateUtil.isSecondTimeBetweenFirstTimeAndThirdTime(lastRecordTimestamp, startTimeOfTheDay, recordTimestamp);
		isFirstOne = isFirstOne || recordTimestamp.equals(startTimeOfTheDay);
		return isFirstOne;
	}

	// 获得tripData
	private TripData getTripDataByVIN(VehicleStandardData stdData) {
		TripData tripData = tripDataMap.get(stdData.getVIN());

		if (tripData == null) { // 对象赋初值
			// 创建新tripData对象
			tripData = new TripData();
			tripDataMap.put(stdData.getVIN(), tripData); // 给hashmap添加新的键值对
		}

		return tripData;
	}
	private void kaishi(VehicleStandardData stdData, TripData tripData) {
		
		/***************************** 需要赋值的变量 *******************************/
		
		/*
		 * 记录行程开始里程表读数
		 */
		Double kaishilichengbiaodushu = stdData.getKilometreMileage();
		tripData.setKaishilichengbiaodushu(kaishilichengbiaodushu);
		
		/*
		 * 车架号
		 */
		String vin = stdData.getVIN();
		tripData.setVin(vin);

		/*
		 * 开始位置信息
		 */
		LocationInformation kaishiweizhixinxi = getLocationInformation(stdData);
		tripData.setKaishiweizhixinxi(kaishiweizhixinxi);

		/*
		 * 开始时间
		 */
		Date kaishishijian = stdData.getRecordTimestamp();
		tripData.setKaishishijian(kaishishijian);

		/*
		 * 开始位置的日出时间，行程开始时计算，依赖数据产生时间
		 */
		NightDriving nd = new NightDriving(stdData.getRecordTimestamp());
		Date sunRiseTimeOfTheDay = nd.getSunRiseTimeOfTheDay();
		tripData.setSunRiseTimeOfTheDay(sunRiseTimeOfTheDay);

		/*
		 * 开始位置的日落时间，行程开始时计算，依赖数据产生时间
		 */
		Date sunSetTimeOfTheDay = nd.getSunSetTimeOfTheDay();
		tripData.setSunSetTimeOfTheDay(sunSetTimeOfTheDay);

		/*
		 * 行程开始当日的0点时间
		 */
		Date startTimeOfTheDay = nd.getStartTimeOfTheDay();
		tripData.setStartTimeOfTheDay(startTimeOfTheDay);

		/*
		 * 行程开始当日的23点59分59秒
		 */
		Date endTimeOfTheDay = nd.getEndTimeOfTheDay();
		tripData.setEndTimeOfTheDay(endTimeOfTheDay);
		
		/*
		 * 高峰驾驶时长
		 */

		RushHour rushHour = new RushHour(stdData.getRecordTimestamp());
		// 获取第一次高峰开始时间
		Date sRushTime1 = rushHour.getsRushTime1();
		tripData.setsRushTime1(sRushTime1);
		// 获取第一次高峰结束时间
		Date eRushTime1 = rushHour.geteRushTime1();
		tripData.seteRushTime1(eRushTime1);
		// 获取第二次高峰开始时间
		Date sRushTime2 = rushHour.getsRushTime2();
		tripData.setsRushTime2(sRushTime2);
		// 获取第二次高峰结束时间
		Date eRushTime2 = rushHour.geteRushTime2();
		tripData.seteRushTime2(eRushTime2);

		/***************************** 需要赋值的中间变量 *******************************/
		
		Date zeroSpeedStartTime = null;
		tripData.setZeroSpeedStartTime(zeroSpeedStartTime);
		Date zeroSpeedEndTime = null;
		tripData.setZeroSpeedEndTime(zeroSpeedEndTime);
		Boolean isDelay = false;
		tripData.setIsDelay(isDelay);
		
		Double sRushTime1Mileage = null;
		tripData.setsRushTime1Mileage(sRushTime1Mileage);
		Double eRushTime1Mileage = null;
		tripData.seteRushTime1Mileage(eRushTime1Mileage);
		Double sRushTime2Mileage = null;
		tripData.setsRushTime2Mileage(sRushTime2Mileage);
		Double eRushTime2Mileage = null;
		tripData.seteRushTime2Mileage(eRushTime2Mileage);
		
		/*
		 * 打分程序的各种变量
		 */
		Double zeroAcc = 0.0;
		tripData.setZeroAcc(zeroAcc);
		Double FreWQACC = 0.0;
		tripData.setFreWQACC(FreWQACC);
		Integer count_acc = 0;
		tripData.setCount_acc(count_acc);
		Double sum_acc = 0.0;
		tripData.setSum_acc(sum_acc);
		Double FreWQDCC = 0.0;
		tripData.setFreWQDCC(FreWQDCC);
		Integer count_dcc = 0;
		tripData.setCount_dcc(count_dcc);
		Double sum_dcc = 0.0;
		tripData.setSum_dcc(sum_dcc);
		Double FreWQTCC = 0.0;
		tripData.setFreWQTCC(FreWQTCC);
		Integer count_tcc = 0;
		tripData.setCount_tcc(count_tcc);
		Double sum_tcc = 0.0;
		tripData.setSum_tcc(sum_tcc);

		/*
		 * 
		 * 以下为车速的一些变量，包括最大车速，加速度，减速度，还有横向加速度，标准差， 急加速，急减速，急转弯等
		 */
		Double zongjiasudu = 0.0;
		tripData.setZongjiasudu(zongjiasudu);
		Double zongjiansudu = 0.0;
		tripData.setZongjiansudu(zongjiansudu);
		Double zongjiasudupingfang = 0.0;
		tripData.setZongjiasudupingfang(zongjiasudupingfang);
		Double zongjiansudupingfang = 0.0;
		tripData.setZongjiansudupingfang(zongjiansudupingfang);
		Double zonghengxiangjiasudupingfang = 0.0;
		tripData.setZonghengxiangjiasudupingfang(zonghengxiangjiasudupingfang);
		Double zonghengxiangjiasudu = 0.0;
		tripData.setZonghengxiangjiasudu(zonghengxiangjiasudu);
		Integer jiasucishu = 0;
		tripData.setJiasucishu(jiasucishu);
		Integer jiansucishu = 0;
		tripData.setJiansucishu(jiansucishu);
		
		/*
		 * 以下为胎压变量
		 */
		Double zongtaiya_qianzuo = 0.0;
		tripData.setZongtaiya_qianzuo(zongtaiya_qianzuo);
		Double zongtaiya_qianyou = 0.0;
		tripData.setZongtaiya_qianyou(zongtaiya_qianyou);
		Double zongtaiya_houzuo = 0.0;
		tripData.setZongtaiya_houzuo(zongtaiya_houzuo);
		Double zongtaiya_houyou = 0.0;
		tripData.setZongtaiya_houyou(zongtaiya_houyou);
		
		/*
		 * 以下为夜间驾驶的变量
		 */
		Date yejianjiashizhongjianshijian = null;
		tripData.setYejianjiashizhongjianshijian(yejianjiashizhongjianshijian);

		Double zongsudu = 0.0;
		tripData.setZongsudu(zongsudu);

		Double zongfadongjizhuansu = 0.0;
		tripData.setZongfadongjizhuansu(zongfadongjizhuansu);

		Double yejianjiashigonglishu = 0.0;
		tripData.setYejianjiashigonglishu(yejianjiashigonglishu);

		// 怠速标志(false非怠速状态，true怠速状态）
		Boolean idleFlag = false;
		tripData.setIdleFlag(idleFlag);
		
		Boolean rapidAccFlag = false;
		tripData.setRapidAccFlag(rapidAccFlag);
		Boolean rapidDccFlag = false;
		tripData.setRapidDccFlag(rapidDccFlag);
		Boolean sharpTurnFlag = false;
		tripData.setSharpTurnFlag(sharpTurnFlag);
		
		/*
		 * 里程长度
		 */
		Double lichengchangdu = 0.0;
		tripData.setLichengchangdu(lichengchangdu);

		/*
		 * 结束位置信息
		 */
		LocationInformation jieshuweizhixinxi = null;
		tripData.setJieshuweizhixinxi(jieshuweizhixinxi);

		/*
		 * 结束时间
		 */
		Date jieshushijian = null;
		tripData.setJieshushijian(jieshushijian);

		/*
		 * Trip 时间长度
		 */
		Long tripshijianchangdu = 0L;
		tripData.setTripshijianchangdu(tripshijianchangdu);

		/*
		 * 平均油耗
		 */
		Double pingjunyouhao = 0.0;
		tripData.setPingjunyouhao(pingjunyouhao);

		/*
		 * 二氧化碳排放量
		 */
		Double eryanghuatanpaifangliang = 0.0;
		tripData.setEryanghuatanpaifangliang(eryanghuatanpaifangliang);

		// 左前轮平均胎压
		Double pingjuntaiya_qianzuo = 0.0;
		tripData.setPingjuntaiya_qianzuo(pingjuntaiya_qianzuo);
		// 右前轮平均胎压
		Double pingjuntaiya_qianyou = 0.0;
		tripData.setPingjuntaiya_qianyou(pingjuntaiya_qianyou);
		// 左后轮平均胎压
		Double pingjuntaiya_houzuo = 0.0;
		tripData.setPingjuntaiya_houzuo(pingjuntaiya_houzuo);
		// 右后轮平均胎压
		Double pingjuntaiya_houyou = 0.0;
		tripData.setPingjuntaiya_houyou(pingjuntaiya_houyou);

		// 平均车速
		Double pingjunchesu = 0.0;
		tripData.setPingjunchesu(pingjunchesu);

		// 平均发动机速度
		Double pingjunfadongjisudu = 0.0;
		tripData.setPingjunfadongjisudu(pingjunfadongjisudu);

		/*
		 * 数据丢失率 计算数据丢失率: trip结束时，(trip预期数据量 - 有效的数据量) / trip预期数据量 trip预期数据量 =
		 * Trip时间长度（秒数)
		 */
		Double shujudiushilv = 0.0;
		tripData.setShujudiushilv(shujudiushilv);

		// 加速度平均值
		Double jiasudupingjunzhi = 0.0;
		tripData.setJiasudupingjunzhi(jiasudupingjunzhi);

		// 加速度标准差
		Double jiasudubiaozhuncha = 0.0;
		tripData.setJiasudubiaozhuncha(jiasudubiaozhuncha);

		// 减速度平均值
		Double jiansudupingjunzhi = 0.0;
		tripData.setJiansudupingjunzhi(jiansudupingjunzhi);

		// 减速度标准差
		Double jiansudubiaozhuncha = 0.0;
		tripData.setJiansudubiaozhuncha(jiansudubiaozhuncha);

		// 横向加速度平均值
		Double hengxiangjiasudupingjunzhi = 0.0;
		tripData.setHengxiangjiasudupingjunzhi(hengxiangjiasudupingjunzhi);

		// 横向加速度标准差
		Double hengxiangjiasudubiaozhuncha = 0.0;
		tripData.setHengxiangjiasudubiaozhuncha(hengxiangjiasudubiaozhuncha);

		/*
		 * 夜间驾驶时间
		 */
		// 计算夜间驾驶时长
		Long yejianjiashishijian = 0L;
		tripData.setYejianjiashishijian(yejianjiashishijian);

		// 计算夜间驾驶里程
		Double yejianjiashilicheng = 0.0;
		tripData.setYejianjiashilicheng(yejianjiashilicheng);

		/*
		 * 疲劳驾驶时间
		 */
		Long pilaojiashishijian = 0L;
		tripData.setPilaojiashishijian(pilaojiashishijian);

		// 计算疲劳驾驶里程
		Double pilaojiashilicheng = 0.0;
		tripData.setPilaojiashilicheng(pilaojiashilicheng);

		// 计算高峰行驶时长
		Long gaofengjiashishijian = 0L;
		tripData.setGaofengjiashishijian(gaofengjiashishijian);

		// 计算高峰行驶里程
		Double gaofengjiashilicheng = 0.0;
		tripData.setGaofengjiashilicheng(gaofengjiashilicheng);

		/*
		 * 计算绿色驾驶评分和安全驾驶评分
		 */
		// ecoPoint : double
		tripData.setEcoPoint(0);
		// safePoint : double
		tripData.setSafePoint(0);/*
		 * 日期时间
		 */
		Date recordTimestamp = null;
		tripData.setRecordTimestamp(recordTimestamp);

		/*
		 * 最大车速
		 */
		Double zuidachesu = 0.0;
		tripData.setZuidachesu(zuidachesu);

		/*
		 * 总油耗
		 */
		Double zongyouhao = 0.0;
		tripData.setZongyouhao(zongyouhao);

		/*
		 * 怠速时间长度(包括怠速开始时间)
		 */
		Long daisushijianchangdu = 0L;
		tripData.setDaisushijianchangdu(daisushijianchangdu);
		
		tripData.setSpeedCnt(0);

		/********************************以下是行程中实时更新的结果变量*********************************/
		
		/*
		 * 最大发动机速度
		 */
		Double zuidafadongjisudu = 0.0;
		tripData.setZuidafadongjisudu(zuidafadongjisudu);

		/*
		 * 加速度平均值
		 */

		// 加速度次数
		Integer jiasuducishu = 0;
		tripData.setJiasucishu(jiasuducishu);

		/*
		 * 急加速次数
		 */
		Integer jijiasucishu = 0;
		tripData.setJijiasucishu(jijiasucishu);

		/*
		 * 急减速次数
		 */
		Integer jijiansucishu = 0;
		tripData.setJijiansucishu(jijiansucishu);

		/*
		 * 急转弯次数 横向加速度 > 0.8时，记为一次急转弯
		 */
		Integer jizhuanwancishu = 0;
		tripData.setJizhuanwancishu(jizhuanwancishu);

		/*
		 * 夜间驾驶里程
		 */
		// 日出里程
		Double mileageOfSunRise = 0.0;
		tripData.setMileageOfSunRise(mileageOfSunRise);

		// 日落里程
		Double mileageOfSunSet = 0.0;
		tripData.setMileageOfSunSet(mileageOfSunSet);

		/*
		 * 疲劳驾驶里程
		 */
		// 获得疲劳驾驶起点时刻里程表读数
		Double fatigueDrivingStartMileage = 0.0;
		tripData.setPilaojiashigonglishu(fatigueDrivingStartMileage);
		
		tripData.setYouxiaodeshujuliang(1L);
		tripData.setEngineSpeedCnt(0);
		
		/*
		 * 总加速度标准差
		 */
		tripData.setAccStd(0.0);
		tripData.setSumAcc(stdData.getLongAcceleration());
		tripData.setSumAccSquare(Math.pow(stdData.getLongAcceleration(), 2));
	}

	private void zhongjian(VehicleStandardData stdData, TripData tripData) {
		
		Integer engineSpeedCnt = getEngineSpeedCnt(stdData, tripData);
		tripData.setEngineSpeedCnt(engineSpeedCnt);
		/*
		 * 日期时间
		 */
		Date recordTimestamp = stdData.getRecordTimestamp();
		tripData.setRecordTimestamp(recordTimestamp);

		/*
		 * 最大车速
		 */
		Double zuidachesu = getMaxSpeed(stdData, tripData);
		tripData.setZuidachesu(zuidachesu);

		/*
		 * 总油耗
		 */
		Double zongyouhao = getTotalConsum(stdData, tripData);
		tripData.setZongyouhao(zongyouhao);

		/*
		 * 怠速时间长度(包括怠速开始时间)
		 */
		Long daisushijianchangdu = getIdleInterval(stdData, tripData);
		tripData.setDaisushijianchangdu(daisushijianchangdu);

		/*
		 * 平均胎压
		 */

		// 左前轮总胎压
		Double zongtaiya_qianzuo = getTotalTP_fleft(stdData, tripData);
		tripData.setZongtaiya_qianzuo(zongtaiya_qianzuo);
		// 右前轮总胎压
		Double zongtaiya_qianyou = getTotalTP_fright(stdData, tripData);
		tripData.setZongtaiya_qianyou(zongtaiya_qianyou);
		// 左后轮总胎压
		Double zongtaiya_houzuo = getTotalTP_bleft(stdData, tripData);
		tripData.setZongtaiya_houzuo(zongtaiya_houzuo);
		// 右后轮总胎压
		Double zongtaiya_houyou = getTotalTP_bright(stdData, tripData);
		tripData.setZongtaiya_houyou(zongtaiya_houyou);

		/*
		 * 最大发动机速度
		 */
		Double zuidafadongjisudu = getMaxEngine(stdData, tripData);
		tripData.setZuidafadongjisudu(zuidafadongjisudu);

		/*
		 * 平均车速
		 */
		// 总速度
		Double zongsudu = getTotalSpeed(stdData, tripData);
		tripData.setZongsudu(zongsudu);
		
		Integer speedCnt = getSpeedCnt(stdData, tripData);
		tripData.setSpeedCnt(speedCnt);

		/*
		 * 平均发动机速度
		 */
		// 总发动机转速
		Double zongfadongjizhuansu = getTotalEngine(stdData, tripData);
		tripData.setZongfadongjizhuansu(zongfadongjizhuansu);

		/*
		 * 加速度平均值
		 */

		// 加速度次数
		Integer jiasuducishu = getAccelerationCnt(stdData, tripData);
		tripData.setJiasucishu(jiasuducishu);

		// 加速度和
		Double zongjiasudu = getTotalAcceleration(stdData, tripData);
		tripData.setZongjiasudu(zongjiasudu);

		/*
		 * 加速度标准差
		 */
		// 加速度平方和
		Double zongjiasudupingfang = getTotalSquareAcceleration(stdData,
				tripData);
		tripData.setZongjiasudupingfang(zongjiasudupingfang);

		/*
		 * 急加速次数
		 */
		Integer jijiasucishu = getRapidAccelerationCnt(stdData, tripData);
		tripData.setJijiasucishu(jijiasucishu);

		/*
		 * 减速度平均值
		 */

		// 减速度次数
		Integer jiansucishu = getDecelerationCnt(stdData, tripData);
		tripData.setJiansucishu(jiansucishu);

		// 减速度和
		Double zongjiansudu = getTotalDeceleration(stdData, tripData);
		tripData.setZongjiansudu(zongjiansudu);

		/*
		 * 减速度标准差
		 */
		// 减速度平方和
		Double zongjiansudupingfang = getTotalSquareDeceleration(stdData,
				tripData);
		tripData.setZongjiansudupingfang(zongjiansudupingfang);

		/*
		 * 急减速次数
		 */
		Integer jijiansucishu = getRapidDecelerationCnt(stdData, tripData);
		tripData.setJijiansucishu(jijiansucishu);

		/*
		 * 横向加速度平均值
		 */
		// 横向加速度
		Double hengxiangjiasudu = getLateralAcceleration(stdData);
		// 横向加速度之和
		Double zonghengxiangjiasudu = getTotalLateralAcceleration(tripData,
				hengxiangjiasudu);
		tripData.setZonghengxiangjiasudu(zonghengxiangjiasudu);

		/*
		 * 横向加速度标准差
		 */
		// 横向加速度平方和
		Double zonghengxiangjiasudupingfang = getTotalLateralAccelerationSquare(
				tripData, hengxiangjiasudu);
		tripData.setZonghengxiangjiasudupingfang(zonghengxiangjiasudupingfang);

		/*
		 * 急转弯次数 横向加速度 > 0.8时，记为一次急转弯
		 */
		Integer jizhuanwancishu = getSharpTurnCnt(tripData, hengxiangjiasudu);
		tripData.setJizhuanwancishu(jizhuanwancishu);

		/*
		 * 夜间驾驶里程
		 */
		// 日出里程
		Double mileageOfSunRise = getMileageOfSunRise(stdData, tripData);
		tripData.setMileageOfSunRise(mileageOfSunRise);

		// 日落里程
		Double mileageOfSunSet = getMileageOfSunSet(stdData, tripData);
		tripData.setMileageOfSunSet(mileageOfSunSet);

		/*
		 * 疲劳驾驶里程
		 */
		// 获得疲劳驾驶起点时刻里程表读数
		Double fatigueDrivingStartMileage = getFatigueDrivingStartMileage(
				stdData, tripData);
		tripData.setPilaojiashigonglishu(fatigueDrivingStartMileage);

		/*
		 * 高峰驾驶里程
		 */

		// 获取第一次高峰开始时里程表读数
		Double sRushTime1Mileage = getsRushTime1Mileage(stdData, tripData);
		tripData.setsRushTime1Mileage(sRushTime1Mileage);

		// 获取第一次高峰结束时里程表读数
		Double eRushTime1Mileage = geteRushTime1Mileage(stdData, tripData);
		tripData.seteRushTime1Mileage(eRushTime1Mileage);

		// 获取第二次高峰开始时里程表读数
		Double sRushTime2Mileage = getsRushTime2Mileage(stdData, tripData);
		tripData.setsRushTime2Mileage(sRushTime2Mileage);

		// 获取第二次高峰结束时里程表读数
		Double eRushTime2Mileage = geteRushTime2Mileage(stdData, tripData);
		tripData.seteRushTime2Mileage(eRushTime2Mileage);

		/*
		 * 计算打分程序需要的指标
		 */

		// zeroAcc
		Double zeroAcc = calcZeroAcc(stdData);
		tripData.setZeroAcc(zeroAcc);

		// count_acc
		Integer count_acc = getCount_acc(stdData, tripData);
		tripData.setCount_acc(count_acc);

		// sum_acc
		Double sum_acc = getSum_acc(stdData, tripData);
		tripData.setSum_acc(sum_acc);

		// FreWQACC
		Double FreWQACC = getFreWQACC(stdData, tripData);
		tripData.setFreWQACC(FreWQACC);

		// sum_dcc
		Double sum_dcc = getSum_dcc(stdData, tripData);
		tripData.setSum_dcc(sum_dcc);

		// count_dcc
		Integer count_dcc = getCount_dcc(stdData, tripData);
		tripData.setCount_dcc(count_dcc);

		// FreWQDCC
		Double FreWQDCC = getFreWQDCC(stdData, tripData);
		tripData.setFreWQDCC(FreWQDCC);

		// sum_tcc
		Double sum_tcc = getSum_tcc(stdData, tripData);
		tripData.setSum_tcc(sum_tcc);

		// count_tcc
		Integer count_tcc = getCount_tcc(stdData, tripData);
		tripData.setCount_tcc(count_tcc);

		// FreWQTCC
		Double FreWQTCC = getFreWQTCC(stdData, tripData);
		tripData.setFreWQTCC(FreWQTCC);

		/*
		 * 二氧化碳排放量
		 */
		Double eryanghuatanpaifangliang = getCarbonDioxideEmissions(stdData, tripData);
		tripData.setEryanghuatanpaifangliang(eryanghuatanpaifangliang);
		
		/*
		 * 总加速度标准差
		 */
		tripData.setSumAcc(tripData.getSumAcc() + stdData.getLongAcceleration());
		tripData.setSumAccSquare(tripData.getSumAccSquare() + Math.pow(stdData.getLongAcceleration(), 2));
		tripData.setAccStd(MathUtil.calcStandardDeviation(tripData.getSumAccSquare(), tripData.getSumAcc() / tripData.getYouxiaodeshujuliang(), tripData.getYouxiaodeshujuliang()));
	}

	private Integer getSpeedCnt(VehicleStandardData stdData, TripData tripData) {
		
		Integer speedCnt = tripData.getSpeedCnt();
		Double vSpeed = stdData.getVehicleSpeed();
		
		if (vSpeed > 0) {
			speedCnt = speedCnt + 1;
		}
		
		return speedCnt;
	}

	private void jieshu(VehicleStandardData stdData, TripData tripData) {
		/*
		 * 里程长度
		 */
		Double lichengchangdu = calcTripLength(stdData, tripData);
		tripData.setLichengchangdu(lichengchangdu);

		/*
		 * 结束位置信息
		 */
		LocationInformation jieshuweizhixinxi = getLocationInformation(stdData);
		tripData.setJieshuweizhixinxi(jieshuweizhixinxi);

		/*
		 * 结束时间
		 */
		Date jieshushijian = stdData.getRecordTimestamp();
		tripData.setJieshushijian(jieshushijian);

		/*
		 * Trip 时间长度
		 */
		Long tripshijianchangdu = DateUtil.dateDiff(
				tripData.getJieshushijian(), tripData.getKaishishijian());
		tripData.setTripshijianchangdu(tripshijianchangdu);

		/*
		 * 平均油耗
		 */
		Double pingjunyouhao = getAvgFuelConsumption(tripData);
		tripData.setPingjunyouhao(pingjunyouhao);

		// 左前轮平均胎压
		Double pingjuntaiya_qianzuo = getAVGTP_fleft(stdData, tripData);
		tripData.setPingjuntaiya_qianzuo(pingjuntaiya_qianzuo);
		// 右前轮平均胎压
		Double pingjuntaiya_qianyou = getAVGTP_fright(stdData, tripData);
		tripData.setPingjuntaiya_qianyou(pingjuntaiya_qianyou);
		// 左后轮平均胎压
		Double pingjuntaiya_houzuo = getAVGTP_bleft(stdData, tripData);
		tripData.setPingjuntaiya_houzuo(pingjuntaiya_houzuo);
		// 右后轮平均胎压
		Double pingjuntaiya_houyou = getAVGTP_bright(stdData, tripData);
		tripData.setPingjuntaiya_houyou(pingjuntaiya_houyou);

		// 平均车速
		Double pingjunchesu = getAvgSpeed(tripData);
		tripData.setPingjunchesu(pingjunchesu);

		// 平均发动机速度
		Double pingjunfadongjisudu = getAvgEngineSpeed(tripData);
		tripData.setPingjunfadongjisudu(pingjunfadongjisudu);

		/*
		 * 数据丢失率 计算数据丢失率: trip结束时，(trip预期数据量 - 有效的数据量) / trip预期数据量 trip预期数据量 =
		 * Trip时间长度（秒数)
		 */
		Double shujudiushilv = getDataLossRate(tripData);
		tripData.setShujudiushilv(shujudiushilv);

		// 加速度平均值
		Double jiasudupingjunzhi = getAvgAcceleration(tripData);
		tripData.setJiasudupingjunzhi(jiasudupingjunzhi);

		// 加速度标准差
		Double jiasudubiaozhuncha = getAccelerationStandardDeviation(tripData);
		tripData.setJiasudubiaozhuncha(jiasudubiaozhuncha);

		// 减速度平均值
		Double jiansudupingjunzhi = getAvgDeceleration(tripData);
		tripData.setJiansudupingjunzhi(jiansudupingjunzhi);

		// 减速度标准差
		Double jiansudubiaozhuncha = getDecelerationStandardDeviation(tripData);
		tripData.setJiansudubiaozhuncha(jiansudubiaozhuncha);

		// 横向加速度平均值
		Double hengxiangjiasudupingjunzhi = getAvgLateralAcceleration(tripData);
		tripData.setHengxiangjiasudupingjunzhi(hengxiangjiasudupingjunzhi);

		// 横向加速度标准差
		Double hengxiangjiasudubiaozhuncha = getLateralAccelerationStandardDeviation(tripData);
		tripData.setHengxiangjiasudubiaozhuncha(hengxiangjiasudubiaozhuncha);

		/*
		 * 夜间驾驶时间
		 */
		// 计算夜间驾驶时长
		Long yejianjiashishijian = getNightDrivingInterval(tripData);
		tripData.setYejianjiashishijian(yejianjiashishijian);

		// 计算夜间驾驶里程
		Double yejianjiashilicheng = getNightDrivingLength(stdData, tripData);
		tripData.setYejianjiashilicheng(yejianjiashilicheng);

		/*
		 * 疲劳驾驶时间
		 */
		Long pilaojiashishijian = getFatigueDrivingTimeLength(stdData, tripData);
		tripData.setPilaojiashishijian(pilaojiashishijian);

		// 计算疲劳驾驶里程
		Double pilaojiashilicheng = getFatigueDrivingDistance(stdData, tripData);
		tripData.setPilaojiashilicheng(pilaojiashilicheng);

		// 计算高峰行驶时长
		Long gaofengjiashishijian = getPeakDrivingInterval(tripData);
		tripData.setGaofengjiashishijian(gaofengjiashishijian);

		// 计算高峰行驶里程
		Double gaofengjiashilicheng = getPeakDrivingDistance(stdData, tripData);
		tripData.setGaofengjiashilicheng(gaofengjiashilicheng);

		/*
		 * 计算绿色驾驶评分和安全驾驶评分
		 */
		EconDataGenerator edg = new EconDataGenerator(tripData);
		// ecoPoint : double
		tripData.setEcoPoint(edg.getEcoPoint());
		// safePoint : double
		tripData.setSafePoint(edg.getSafePoint());
	//	System.out.println("绿色行车评分：" + tripData.getEcoPoint() + ", 安全驾驶评分："
		//		+ tripData.getSafePoint());

	}

	private Double getFreWQTCC(VehicleStandardData stdData, TripData tripData) {
		Double FreWQTCC = tripData.getFreWQTCC();
		Integer count_tcc = tripData.getCount_tcc();
		if (count_tcc == 0) {
			return 0.0;
		}
		if (Double.valueOf(getLateralAcceleration(stdData)) > 0.8) {
			FreWQTCC = tripData.getSum_tcc() / count_tcc;
		}
		return FreWQTCC;
	}

	private Integer getCount_tcc(VehicleStandardData stdData, TripData tripData) {
		Integer count_tcc = 0;
		if (Double.valueOf(getLateralAcceleration(stdData)) > 0.8) {
			count_tcc = tripData.getCount_tcc() + 1;
		}
		else
			count_tcc = tripData.getCount_tcc();
		return count_tcc;
	}

	private Double getSum_tcc(VehicleStandardData stdData, TripData tripData) {
		Double sum_tcc = 0.0;
		if (Double.valueOf(getLateralAcceleration(stdData)) > 0.8) {
			sum_tcc = tripData.getSum_tcc()
					+ Double.valueOf(getLateralAcceleration(stdData));
		}
		else
			sum_tcc = tripData.getSum_tcc();
		return sum_tcc;
	}

	private Double getFreWQDCC(VehicleStandardData stdData, TripData tripData) {
		Double FreWQDCC = tripData.getFreWQDCC();
		Integer count_dcc = tripData.getCount_dcc();
		if (count_dcc == 0) {
			return 0.0;
		}
		if (-stdData.getLongAcceleration() < (-1.0 + tripData.getZeroAcc())) {
			FreWQDCC = tripData.getSum_dcc() / count_dcc;
		}
			
		return FreWQDCC;
	}

	private Integer getCount_dcc(VehicleStandardData stdData, TripData tripData) {
		Integer count_dcc = 0;
		if (-stdData.getLongAcceleration() < (-1.0 + tripData.getZeroAcc())) {
			count_dcc = tripData.getCount_dcc() + 1;
		}
		else
			count_dcc = tripData.getCount_dcc();
		return count_dcc;
	}

	private Double getSum_dcc(VehicleStandardData stdData, TripData tripData) {
		Double sum_dcc = 0.0;
		if (-stdData.getLongAcceleration() < (-1.0 + tripData.getZeroAcc())) {
			sum_dcc = tripData.getSum_dcc() - stdData.getLongAcceleration();
		}
		else
			sum_dcc = tripData.getSum_dcc();
		
		return sum_dcc;
	}

	private Double getFreWQACC(VehicleStandardData stdData, TripData tripData) {
		Double FreWQACC = tripData.getFreWQACC();
		Integer count_acc = tripData.getCount_acc();
		if (count_acc == 0) {
			return 0.0;
		}
		if (-stdData.getLongAcceleration() > (1.0 + tripData.getZeroAcc())) {
			FreWQACC = tripData.getSum_acc() / count_acc;
		}
		return FreWQACC;
	}

	private Double getSum_acc(VehicleStandardData stdData, TripData tripData) {
		Double sum_acc = 0.0;
		if (-stdData.getLongAcceleration() > (1.0 + tripData.getZeroAcc())) {
			sum_acc = tripData.getSum_acc() - stdData.getLongAcceleration();
		}
		else
			sum_acc = tripData.getSum_acc();
		
		return sum_acc;
	}

	private Integer getCount_acc(VehicleStandardData stdData, TripData tripData) {
		Integer count_acc = 0;
		if (-stdData.getLongAcceleration() > (1.0 + tripData.getZeroAcc())) {
			count_acc = tripData.getCount_acc() + 1;
		}
		else 
			count_acc = tripData.getCount_acc();
		
		return count_acc;
	}

	private Double geteRushTime2Mileage(VehicleStandardData stdData,
			TripData tripData) {
		Double eRushTime2Mileage = 0.0;
		
		// 判断当前时间是否等于第二次高峰结束时间，或者第二次高峰结束后第一条行车记录产生的时间
		Boolean isERushTime2 = isERushTime2(stdData, tripData);		
		if (isERushTime2) {
			eRushTime2Mileage = stdData.getKilometreMileage();
		}
		return eRushTime2Mileage;
	}

	// 判断当前时间是否等于第二次高峰结束时间，或者第二次高峰结束后第一条行车记录产生的时间
	private Boolean isERushTime2(VehicleStandardData stdData, TripData tripData) {
		// 第二次高峰结束时间
		Date eRushTime2 = tripData.geteRushTime2();
		// 本次行车数据产生时间
		Date recordTimestamp = tripData.getRecordTimestamp();
		// 上次行车数据产生时间
		Date lastRecordTimestamp = this.getLastRecordTimestampByVIN(stdData.getVIN());
		// 判断当前时间是否等于第二次高峰结束时间，或者第二次高峰结束后第一条行车记录产生的时间
		Boolean isERushTime2 = DateUtil.isSecondTimeBetweenFirstTimeAndThirdTime(lastRecordTimestamp, eRushTime2, recordTimestamp);
		isERushTime2 = isERushTime2 || recordTimestamp.equals(eRushTime2);
		return isERushTime2;
	}

	private Double getsRushTime2Mileage(VehicleStandardData stdData,
			TripData tripData) {
		Double sRushTime2Mileage = 0.0;
		
		// 判断当前时点是否为第二次高峰开始时点，或者第二次高峰后第一条行车数据产生时点
		Boolean isSRushTime2 = isSRushTime2(stdData, tripData);
		if (isSRushTime2) {
			sRushTime2Mileage = stdData.getKilometreMileage();
		}
		return sRushTime2Mileage;
	}

	// 判断当前时点是否为第二次高峰开始时点，或者第二次高峰后第一条行车数据产生时点
	private Boolean isSRushTime2(VehicleStandardData stdData, TripData tripData) {
		// 第二次高峰开始时间
		Date sRushTime2 = tripData.getsRushTime2();
		// 本次行车记录产生时间
		Date recordTimestamp = tripData.getRecordTimestamp();
		// 上次行车记录产生时间
		Date lastRecordTimestamp = this.getLastRecordTimestampByVIN(stdData.getVIN());
		// 判断当前时点是否为第二次高峰开始时点，或者第二次高峰后第一条行车数据产生时点
		Boolean isSRushTime2 = DateUtil.isSecondTimeBetweenFirstTimeAndThirdTime(lastRecordTimestamp, sRushTime2, recordTimestamp);
		isSRushTime2 = isSRushTime2 || recordTimestamp.equals(sRushTime2);
		return isSRushTime2;
	}

	private Double geteRushTime1Mileage(VehicleStandardData stdData,
			TripData tripData) {
		Double eRushTime1Mileage = 0.0;
		
		// 判断当前时点是否为第一次高峰结束时点，或者第一次高峰结束后第一条行车数据产生的时间
		Boolean isERushTime1 = isERushTime1(stdData, tripData);
		if (isERushTime1) {
			eRushTime1Mileage = stdData.getKilometreMileage();
		}
		return eRushTime1Mileage;
	}

	// 判断当前时点是否为第一次高峰结束时点，或者第一次高峰结束后第一条行车数据产生的时间
	private Boolean isERushTime1(VehicleStandardData stdData, TripData tripData) {
		// 第一次高峰结束时间
		Date eRushTime1 = tripData.geteRushTime1();
		// 本次行车记录产生时间
		Date recordTimestamp = tripData.getRecordTimestamp();
		// 上次行车记录产生时间
		Date lastRecordTimestamp = this.getLastRecordTimestampByVIN(stdData.getVIN());
		// 判断当前时点是否为第一次高峰结束时点，或者第一次高峰结束后第一条行车数据产生的时间
		Boolean isERushTime1 = DateUtil.isSecondTimeBetweenFirstTimeAndThirdTime(lastRecordTimestamp, eRushTime1, recordTimestamp);
		isERushTime1 = isERushTime1 || recordTimestamp.equals(eRushTime1);
		return isERushTime1;
	}

	private Double getsRushTime1Mileage(VehicleStandardData stdData,
			TripData tripData) {
		Double sRushTime1Mileage = 0.0;
		
		// 判断当前时点是否为第一次高峰开始时点，或第一次高峰开始后的第一条数据发送时点
		Boolean isSRushTime1 = isSRushTime1(stdData, tripData);
		if (isSRushTime1) {
			sRushTime1Mileage = stdData.getKilometreMileage();
		}
		return sRushTime1Mileage;
	}
	
	// 判断当前时点是否为第一次高峰开始时点，或第一次高峰开始后的第一次数据发送时点
	private Boolean isSRushTime1(VehicleStandardData stdData, TripData tripData) {
		// 第一次高峰开始时间
		Date sRushTime1 = tripData.getsRushTime1();
		// 本次行车数据产生时间
		Date recordTimestamp = tripData.getRecordTimestamp();
		// 上次行车数据产生时间
		Date lastRecordTimestamp = this.getLastRecordTimestampByVIN(stdData.getVIN());
		Boolean isSRushTime1 = DateUtil.isSecondTimeBetweenFirstTimeAndThirdTime(lastRecordTimestamp, sRushTime1, recordTimestamp);
		isSRushTime1 = isSRushTime1 || sRushTime1.equals(recordTimestamp);
		return isSRushTime1;
	}

	/*
	 * 高峰驾驶里程 
	 * 
	 * 每日有两个车辆行驶高峰时段，高峰时段将一天划分为5段： 
	 * 1. [每日0点0分0秒， 第一次高峰开始时间), 
	 * 2. [第一次高峰开始时间， 第一次高峰结束时间), 
	 * 3. [第一次高峰结束时间， 第二次高峰开始时间), 
	 * 4. [第二次高峰开始时间，第二次高峰结束时间), 
	 * 5. [第二次高峰结束时间， 每日23点59分59秒)
	 * 经过排列组合统计，发生在这5个时间段的行程可能有15种情况，其中12种情况涉及高峰驾驶， 下面将15种情况一一列举，并提供该情况下的计算公式：
	 * 一、第一次高峰前启动车辆 
	 * 1. 第一次高峰开始前结束行程，该时段不会产生高峰行车数据 
	 * 2. 第一次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 第一次高峰开始里程 
	 * 3. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 第一次高峰开始里程 
	 * 4. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 第一次高峰开始里程 + 结束里程 - 第二次高峰开始里程 
	 * 5. 第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束里程 - 第二次高峰开始里程 + 第一次高峰结束里程 - 第一次高峰开始里程
	 * 二、第一次高峰期间启动车辆 
	 * 6. 第一次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 开始里程 
	 * 7. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 开始里程 
	 * 8. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 开始里程 + 结束里程 - 第二次高峰开始里程 
	 * 9. 第二次高峰结束后结束行程，高峰驾驶时长 = 结束里程 - 第二次高峰开始里程 + 第一次高峰结束里程 - 第一次高峰开始里程 
	 * 三、两次高峰之间启动车辆 
	 * 10.两次高峰之间结束行程，高峰驾驶时长 ，该时段不会产生高峰行车数据
	 * 11.第二次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 第二次高峰开始里程 
	 * 12.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束里程 - 第二次高峰开始里程 四、第二次高峰期间启动车辆 
	 * 13.第二次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 开始里程
	 * 14.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束里程 - 开始里程 五、第二次高峰结束启动车辆
	 * 15.第二次高峰结束后结束行程，该时段不会产生高峰行车数据
	 * 
	 * 综上，计算高峰行驶时长需要如下数据： 开始里程、结束里程、第一次高峰开始里程、第一次高峰结束里程、第二次高峰开始里程、第二次高峰结束里程、
	 * 开始时间、结束时间、第一次高峰开始时间、第一次高峰结束时间、第二次高峰开始时间、第二次高峰结束时间
	 */
	private Double getPeakDrivingDistance(VehicleStandardData stdData,
			TripData tripData) {

		// 开始时间
		Date kaishishijian = tripData.getKaishishijian();
		// 结束时间
		Date jieshushijian = tripData.getJieshushijian();
		// 第一次高峰开始时间
		Date sRushTime1 = tripData.getsRushTime1();
		// 第一次高峰结束时间
		Date eRushTime1 = tripData.geteRushTime1();
		// 第二次高峰开始时间
		Date sRushTime2 = tripData.getsRushTime2();
		// 第二次高峰结束时间
		Date eRushTime2 = tripData.geteRushTime2();

		// 开始里程
		Double kaishilichengbiaodushu = tripData.getKaishilichengbiaodushu();
		// 结束里程
		Double jieshulichengbiaodushu = stdData.getKilometreMileage();
		// 第一次高峰开始里程
		Double sRushTime1Mileage = tripData.getsRushTime1Mileage();
		// 第一次高峰结束里程
		Double eRushTime1Mileage = tripData.geteRushTime1Mileage();
		// 第二次高峰开始里程
		Double sRushTime2Mileage = tripData.getsRushTime2Mileage();
		// 第二次高峰结束里程
		Double eRushTime2Mileage = tripData.geteRushTime2Mileage();

		Double gaofengjiashilicheng = 0.0;
		// 一、第一次高峰前启动车辆
		if (kaishishijian.before(sRushTime1)) {
			// 1. 第一次高峰开始前结束行程，该时段不会产生高峰行车数据
			if (jieshushijian.before(sRushTime1)) {
				gaofengjiashilicheng = 0.0;
			}
			// 2. 第一次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 第一次高峰开始里程
			if ((jieshushijian.equals(sRushTime1) || jieshushijian
					.after(sRushTime1)) && jieshushijian.before(eRushTime1)) {
				gaofengjiashilicheng = jieshulichengbiaodushu
						- sRushTime1Mileage;
			}
			// 3. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 第一次高峰开始里程
			if ((jieshushijian.equals(eRushTime1) || jieshushijian
					.after(eRushTime1)) && jieshushijian.before(sRushTime2)) {
				gaofengjiashilicheng = eRushTime1Mileage - sRushTime1Mileage;
			}
			// 4. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 第一次高峰开始里程 + 结束里程 - 第二次高峰开始里程
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashilicheng = eRushTime1Mileage - sRushTime1Mileage
						+ jieshulichengbiaodushu - sRushTime2Mileage;
			}
			// 5. 第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束里程 - 第二次高峰开始里程 + 第一次高峰结束里程 -
			// 第一次高峰开始里程
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashilicheng = eRushTime2Mileage - sRushTime2Mileage
						+ eRushTime1Mileage - sRushTime1Mileage;
			}
		}
		// 二、第一次高峰期间启动车辆
		if ((kaishishijian.equals(sRushTime1) || kaishishijian
				.after(sRushTime1)) && kaishishijian.before(eRushTime1)) {
			// 6. 第一次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 开始里程
			if ((jieshushijian.equals(sRushTime1) || jieshushijian
					.after(sRushTime1)) && jieshushijian.before(eRushTime1)) {
				gaofengjiashilicheng = jieshulichengbiaodushu
						- kaishilichengbiaodushu;
			}
			// 7. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 开始里程
			if ((jieshushijian.equals(eRushTime1) || jieshushijian
					.after(eRushTime1)) && jieshushijian.before(sRushTime2)) {
				gaofengjiashilicheng = eRushTime1Mileage
						- kaishilichengbiaodushu;
			}
			// 8. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束里程 - 开始里程 + 结束里程 - 第二次高峰开始里程
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashilicheng = eRushTime1Mileage
						- kaishilichengbiaodushu + jieshulichengbiaodushu
						- sRushTime2Mileage;
			}
			// 9. 第二次高峰结束后结束行程，高峰驾驶时长 = 结束里程 - 第二次高峰开始里程 + 第一次高峰结束里程 - 第一次高峰开始里程
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashilicheng = jieshulichengbiaodushu
						- sRushTime2Mileage + eRushTime1Mileage
						- sRushTime1Mileage;
			}
		}
		// 三、两次高峰之间启动车辆
		if ((kaishishijian.equals(eRushTime1) || kaishishijian
				.after(eRushTime1)) && kaishishijian.before(sRushTime2)) {
			// 10.两次高峰之间结束行程，高峰驾驶时长 ，该时段不会产生高峰行车数据
			if ((jieshushijian.equals(eRushTime1) || jieshushijian
					.after(eRushTime1)) && jieshushijian.before(sRushTime2)) {
				gaofengjiashilicheng = 0.0;
			}
			// 11.第二次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 第二次高峰开始里程
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashilicheng = jieshulichengbiaodushu
						- sRushTime1Mileage;
			}
			// 12.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束里程 - 第二次高峰开始里程
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashilicheng = eRushTime1Mileage - sRushTime2Mileage;
			}
		}
		// 四、第二次高峰期间启动车辆
		if ((kaishishijian.equals(sRushTime2) || kaishishijian
				.after(sRushTime2)) && kaishishijian.before(eRushTime2)) {
			// 13.第二次高峰期间结束行程，高峰驾驶时长 = 结束里程 - 开始里程
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashilicheng = jieshulichengbiaodushu
						- kaishilichengbiaodushu;
			}
			// 14.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束里程 - 开始里程
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashilicheng = eRushTime2Mileage
						- kaishilichengbiaodushu;
			}
		}
		// 五、第二次高峰结束启动车辆
		if (kaishishijian.after(eRushTime2)) {
			// 15.第二次高峰结束后结束行程，该时段不会产生高峰行车数据
			gaofengjiashilicheng = 0.0;
		}
		return gaofengjiashilicheng;
	}

	/*
	 * 高峰驾驶时长 每日有两个车辆行驶高峰时段，高峰时段将一天划分为5段： 
	 * 1. [每日0点0分0秒， 第一次高峰开始时间), 
	 * 2. [第一次高峰开始时间， 第一次高峰结束时间), 
	 * 3. [第一次高峰结束时间， 第二次高峰开始时间), 
	 * 4. [第二次高峰开始时间，第二次高峰结束时间), 
	 * 5. [第二次高峰结束时间， 每日23点59分59秒)
	 * 
	 * 经过排列组合统计，发生在这5个时间段的行程可能有15种情况，其中12种情况涉及高峰驾驶， 下面将15种情况一一列举，并提供该情况下的计算公式：
	 * 
	 * 一、第一次高峰前启动车辆
	 * 1. 第一次高峰开始前结束行程，该时段不会产生高峰行车数据 
	 * 2. 第一次高峰期间结束行程，高峰驾驶时长 = 结束时间 -第一次高峰开始时间 
	 * 3. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 第一次高峰开始时间 
	 * 4. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 第一次高峰开始时间 + 结束时间 - 第二次高峰开始时间 
	 * 5. 第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束时间 - 第二次高峰开始时间 + 第一次高峰结束时间 - 第一次高峰开始时间
	 * 二、第一次高峰期间启动车辆 
	 * 6. 第一次高峰期间结束行程，高峰驾驶时长 = 结束时间 - 开始时间 
	 * 7. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 开始时间 
	 * 8. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 开始时间 + 结束时间 - 第二次高峰开始时间 
	 * 9. 第二次高峰结束后结束行程，高峰驾驶时长 = 结束时间 - 第二次高峰开始时间 + 第一次高峰结束时间 -第一次高峰开始时间 
	 * 三、两次高峰之间启动车辆 
	 * 10.两次高峰之间结束行程，高峰驾驶时长 ，该时段不会产生高峰行车数据
	 * 11.第二次高峰期间结束行程，高峰驾驶时长 = 结束时间 - 第二次高峰开始时间 
	 * 12.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束时间 - 第二次高峰开始时间 
	 * 四、第二次高峰期间启动车辆 
	 * 13.第二次高峰期间结束行程，高峰驾驶时长 = 结束时间 - 开始时间
	 * 14.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束时间 - 开始时间 
	 * 五、第二次高峰结束启动车辆
	 * 15.第二次高峰结束后结束行程，该时段不会产生高峰行车数据
	 * 
	 * 综上，计算高峰行驶时长需要如下数据：开始时间、结束时间、第一次高峰开始时间、第一次高峰结束时间、第二次高峰开始时间、第二次高峰结束时间
	 */
	private Long getPeakDrivingInterval(TripData tripData) {
		
		Long gaofengjiashishijian = 0L;

		// 开始时间
		Date kaishishijian = tripData.getKaishishijian();
		// 结束时间
		Date jieshushijian = tripData.getJieshushijian();
		// 第一次高峰开始时间
		Date sRushTime1 = tripData.getsRushTime1();
		// 第一次高峰结束时间
		Date eRushTime1 = tripData.geteRushTime1();
		// 第二次高峰开始时间
		Date sRushTime2 = tripData.getsRushTime2();
		// 第二次高峰结束时间
		Date eRushTime2 = tripData.geteRushTime2();

		// 一、第一次高峰前启动车辆
		if (kaishishijian.before(sRushTime1)) {
			// 1. 第一次高峰开始前结束行程，该时段不会产生高峰行车数据
			if (jieshushijian.before(sRushTime1)) {
				gaofengjiashishijian = 0L;
			}
			// 2. 第一次高峰期间结束行程，高峰驾驶时长 = 结束时间 - 第一次高峰开始时间
			if ((jieshushijian.equals(sRushTime1) || jieshushijian
					.after(sRushTime1)) && jieshushijian.before(eRushTime1)) {
				gaofengjiashishijian = DateUtil.dateDiff(jieshushijian,
						sRushTime1);
			}
			// 3. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 第一次高峰开始时间
			if ((jieshushijian.equals(eRushTime1) || jieshushijian
					.after(eRushTime1)) && jieshushijian.before(sRushTime2)) {
				gaofengjiashishijian = DateUtil
						.dateDiff(eRushTime1, sRushTime1);
			}
			// 4. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 第一次高峰开始时间 + 结束时间 - 第二次高峰开始时间
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashishijian = DateUtil
						.dateDiff(eRushTime1, sRushTime1)
						+ DateUtil.dateDiff(jieshushijian, sRushTime2);
			}
			// 5. 第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束时间 - 第二次高峰开始时间 + 第一次高峰结束时间 -
			// 第一次高峰开始时间
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashishijian = DateUtil
						.dateDiff(eRushTime1, sRushTime1)
						+ DateUtil.dateDiff(eRushTime2, sRushTime2);
			}
		}
		// 二、第一次高峰期间启动车辆
		if ((kaishishijian.equals(sRushTime1) || kaishishijian
				.after(sRushTime1)) && kaishishijian.before(eRushTime1)) {
			// 6. 第一次高峰期间结束行程，高峰驾驶时长 = 结束时间 - 开始时间
			if ((jieshushijian.equals(sRushTime1) || jieshushijian
					.after(sRushTime1)) && jieshushijian.before(eRushTime1)) {
				gaofengjiashishijian = DateUtil.dateDiff(jieshushijian,
						kaishishijian);
			}
			// 7. 两次高峰之间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 开始时间
			if ((jieshushijian.equals(eRushTime1) || jieshushijian
					.after(eRushTime1)) && jieshushijian.before(sRushTime2)) {
				gaofengjiashishijian = DateUtil.dateDiff(eRushTime1,
						kaishishijian);
			}
			// 8. 第二次高峰期间结束行程，高峰驾驶时长 = 第一次高峰结束时间 - 开始时间 + 结束时间 - 第二次高峰开始时间
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashishijian = DateUtil.dateDiff(eRushTime1,
						kaishishijian)
						+ DateUtil.dateDiff(jieshushijian, sRushTime2);
			}
			// 9. 第二次高峰结束后结束行程，高峰驾驶时长 = 结束时间 - 第二次高峰开始时间 + 第一次高峰结束时间 - 第一次高峰开始时间
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashishijian = DateUtil.dateDiff(jieshushijian,
						sRushTime2) + DateUtil.dateDiff(eRushTime1, sRushTime1);
			}
		}
		// 三、两次高峰之间启动车辆
		if ((kaishishijian.equals(eRushTime1) || kaishishijian
				.after(eRushTime1)) && kaishishijian.before(sRushTime2)) {
			// 10.两次高峰之间结束行程，高峰驾驶时长 ，该时段不会产生高峰行车数据
			if ((jieshushijian.equals(eRushTime1) || jieshushijian
					.after(eRushTime1)) && jieshushijian.before(sRushTime2)) {
				gaofengjiashishijian = 0L;
			}
			// 11.第二次高峰期间结束行程，高峰驾驶时长 = 结束时间 - 第二次高峰开始时间
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashishijian = DateUtil.dateDiff(jieshushijian,
						sRushTime2);
			}
			// 12.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束时间 - 第二次高峰开始时间
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashishijian = DateUtil
						.dateDiff(eRushTime2, sRushTime2);
			}
		}
		// 四、第二次高峰期间启动车辆
		if ((kaishishijian.equals(sRushTime2) || kaishishijian
				.after(sRushTime2)) && kaishishijian.before(eRushTime2)) {
			// 13.第二次高峰期间结束行程，高峰驾驶时长 = 结束时间 - 开始时间
			if ((jieshushijian.equals(sRushTime2) || jieshushijian
					.equals(sRushTime2)) && jieshushijian.before(eRushTime2)) {
				gaofengjiashishijian = DateUtil.dateDiff(jieshushijian,
						kaishishijian);
			}
			// 14.第二次高峰结束后结束行程，高峰驾驶时长 = 第二次高峰结束时间 - 开始时间
			if (jieshushijian.after(eRushTime2)) {
				gaofengjiashishijian = DateUtil.dateDiff(eRushTime2,
						kaishishijian);
			}
		}
		// 五、第二次高峰结束启动车辆
		if (kaishishijian.after(eRushTime2)) {
			// 15.第二次高峰结束后结束行程，该时段不会产生高峰行车数据
			gaofengjiashishijian = 0L;
		}
		return gaofengjiashishijian;
	}

	private Double getFatigueDrivingDistance(VehicleStandardData stdData,
			TripData tripData) {
		Double pilaojiashilicheng = 0.0;
		if (DateUtil.dateDiff(stdData.getRecordTimestamp(),
				tripData.getKaishishijian()) > 3 * 60 * 60 * 1000) {
			pilaojiashilicheng = stdData.getKilometreMileage()
					- tripData.getPilaojiashigonglishu(); // 疲劳驾驶里程
		}
		return pilaojiashilicheng;
	}

	private Double getFatigueDrivingStartMileage(VehicleStandardData stdData,
			TripData tripData) {
		Double fatigueDrivingStartMileage = 0.0;
		// 获取疲劳驾驶起点时刻的里程表读数
		if (DateUtil.dateDiff(stdData.getRecordTimestamp(),
				tripData.getKaishishijian()) == 3 * 60 * 60 * 1000) {
			fatigueDrivingStartMileage = stdData.getKilometreMileage();
		}
		return fatigueDrivingStartMileage;
	}

	private Long getFatigueDrivingTimeLength(VehicleStandardData stdData,
			TripData tripData) {
		Long pilaojiashishijian = 0L;
		if (DateUtil.dateDiff(stdData.getRecordTimestamp(),
				tripData.getKaishishijian()) > 3 * 60 * 60 * 1000) {
			pilaojiashishijian = DateUtil.dateDiff(
					stdData.getRecordTimestamp(), tripData.getKaishishijian())
					- 3 * 60 * 60 * 1000;
		}
		return pilaojiashishijian;
	}

	private Double getMileageOfSunSet(VehicleStandardData stdData,
			TripData tripData) {
		Double mileageOfSunSet = 0.0;		
		Boolean isSunSet = isSunSet(stdData, tripData);
		
		// 判断当前时点是否为日落时间，或者日落后第一条数据生产时间
		if (isSunSet) {
			mileageOfSunSet = stdData.getKilometreMileage();
		}
		
		return mileageOfSunSet;
	}

	// 判断当前时点是否为日落时间，或者日落后第一条数据产生时间
	private Boolean isSunSet(VehicleStandardData stdData, TripData tripData) {
		// 获得上一次行车记录产生时间
		Date lastRecordTimestamp = this.getLastRecordTimestampByVIN(stdData.getVIN());
		// 获得当前行车记录产生时间
		Date recordTimestamp = stdData.getRecordTimestamp();
		// 获得当日日落时间
		Date sunSetTimeOfTheDay = tripData.getSunSetTimeOfTheDay();
		// 比较上一次行车数据产生时间、当日日落时间、当前行车数据产生时间，判断当前时刻是否为日落时刻
		Boolean isSunSet = DateUtil.isSecondTimeBetweenFirstTimeAndThirdTime(lastRecordTimestamp, sunSetTimeOfTheDay, recordTimestamp);
		isSunSet = isSunSet || recordTimestamp.equals(sunSetTimeOfTheDay);
		return isSunSet;
	}

	private Double getMileageOfSunRise(VehicleStandardData stdData,
			TripData tripData) {
		Double mileageOfSunRise = 0.0;		
		// 判断当前时点是否为日出时间，或者日出后第一条数据的产生时间
		Boolean isSunRise = isSunRise(stdData, tripData);
		if (isSunRise) {
			mileageOfSunRise = stdData.getKilometreMileage();
		}		
		
		return mileageOfSunRise;
	}

	// 判断当前时点是否为日出时间，或者日出后第一条数据的产生时间
	private Boolean isSunRise(VehicleStandardData stdData, TripData tripData) {
		// 获得上一次行车记录产生时间
		Date lastRecordTimestamp = this.getLastRecordTimestampByVIN(stdData.getVIN());
		// 获得当前行车记录产生时间
		Date recordTimestamp = stdData.getRecordTimestamp();
		// 获得当日日出时间
		Date sunRiseTimeOfTheDay = tripData.getSunRiseTimeOfTheDay();
		// 比较上一次行车数据产生时间、当日日出时间、当前行车数据产生时间，判断当前时刻是否为日出时刻
		Boolean isSunRise = DateUtil.isSecondTimeBetweenFirstTimeAndThirdTime(lastRecordTimestamp, sunRiseTimeOfTheDay, recordTimestamp);
		isSunRise = isSunRise || recordTimestamp.equals(isSunRise);		
		return isSunRise;
	}

	/*
	 * 
	 * 夜间驾驶里程：夜间驾驶里程是满足夜间驾驶条件下一到多个夜间驾驶里程的总和
	 * 
	 * 首先要考虑的是一次夜间驾驶里程的计算实现：
	 * 
	 * 计算夜间驾驶里程
	 * 
	 * 假设一次里程最大持续时间小于20小时，当行驶里程跨越两天时，需以0点为界一分为二
	 * 一天的时间被日出日落时间分为三个区间：[0点，日出），[日出，日落），[日落，0点） 行驶里程按照排列组合在这三个区间中有6种情况：
	 * 
	 * 1.开始时间位于第一区间 1.1 结束时间位于第一区间：夜间行驶里程 = 结束里程 - 开始里程 1.2 结束时间位于第二区间：夜间行驶里程 =
	 * 日出里程 - 开始里程 1.3 结束时间位于第三区间：夜间行驶里程 = 日出里程 - 开始里程 + 结束里程 - 日落里程
	 * 
	 * 2.开始时间位于第二区间 2.1 结束时间位于第二区间：夜间行驶里程 = 0 2.2 结束时间位于第三区间：夜间行驶里程 = 结束里程 -
	 * 日落里程
	 * 
	 * 3.开始时间位于第三区间 3.1 结束时间位于第三区间：夜间行驶里程 = 结束里程 - 开始里程
	 * 
	 * 综上，计算夜间行驶时间需要：开始时间、结束时间、日出时间、日落时间、开始里程、结束里程、日出里程、日落里程
	 * 
	 * 在此基础上，将本次计算获得的夜间驾驶时间进行累加：夜间驾驶里程 = 夜间驾驶里程 + 本次求得的夜间驾驶里程
	 */
	private Double getNightDrivingLength(VehicleStandardData stdData,
			TripData tripData) {

		Double yejianjiashilicheng = 0.0;
		// 开始时间
		Date kaishishijian = tripData.getKaishishijian();
		// 结束时间
		Date jieshushijian = tripData.getJieshushijian();

		// 日出时间
		Date sunRiseTimeOfTheDay = tripData.getSunRiseTimeOfTheDay();
		// 日落时间
		Date sunSetTimeOfTheDay = tripData.getSunSetTimeOfTheDay();

		// 开始里程
		Double kaishilichengbiaodushu = tripData.getKaishilichengbiaodushu();
		// 结束里程
		Double jieshulichengbiaodushu = stdData.getKilometreMileage();
		// 日出里程
		Double mileageOfSunRise = tripData.getMileageOfSunRise();
		// 日落里程
		Double mileageOfSunSet = tripData.getMileageOfSunSet();

		// 1.开始时间位于第一区间
		if (kaishishijian.before(sunRiseTimeOfTheDay)) {
			// 1.1 结束时间位于第一区间：夜间行驶里程 = 结束里程 - 开始里程
			if (jieshushijian.before(sunRiseTimeOfTheDay)) {
				yejianjiashilicheng = jieshulichengbiaodushu - kaishilichengbiaodushu;
			}
			// 1.2 结束时间位于第二区间：夜间行驶里程 = 日出里程 - 开始里程
			if ((jieshushijian.equals(sunRiseTimeOfTheDay) || jieshushijian
					.after(sunRiseTimeOfTheDay))
					&& jieshushijian.before(sunSetTimeOfTheDay)) {
				yejianjiashilicheng = mileageOfSunRise - kaishilichengbiaodushu;
			}
			// 1.3 结束时间位于第三区间：夜间行驶里程 = 日出里程 - 开始里程 + 结束里程 - 日落里程
			if (jieshushijian.equals(sunSetTimeOfTheDay)
					|| jieshushijian.after(sunSetTimeOfTheDay)) {
				yejianjiashilicheng = mileageOfSunRise - kaishilichengbiaodushu
						+ jieshulichengbiaodushu - mileageOfSunSet;
			}
		}
		// 2.开始时间位于第二区间
		if ((kaishishijian.equals(sunRiseTimeOfTheDay) || kaishishijian
				.after(sunRiseTimeOfTheDay))
				&& kaishishijian.before(sunSetTimeOfTheDay)) {
			// 2.1 结束时间位于第二区间：夜间行驶里程 = 0
			if ((jieshushijian.equals(sunRiseTimeOfTheDay) || jieshushijian
					.after(sunRiseTimeOfTheDay))
					&& jieshushijian.before(sunSetTimeOfTheDay)) {
				yejianjiashilicheng = 0.0;
			}
			// 2.2 结束时间位于第三区间：夜间行驶里程 = 结束里程 - 日落里程
			if (jieshushijian.equals(sunSetTimeOfTheDay)
					|| jieshushijian.after(sunSetTimeOfTheDay)) {
				yejianjiashilicheng = jieshulichengbiaodushu - mileageOfSunSet;
			}
		}
		// 3.开始时间位于第三区间
		if (kaishishijian.equals(sunSetTimeOfTheDay)
				|| kaishishijian.after(sunSetTimeOfTheDay)) {
			// 3.1 结束时间位于第三区间：夜间行驶里程 = 结束里程 - 开始里程
			yejianjiashilicheng = jieshulichengbiaodushu - kaishilichengbiaodushu;
		}
		return yejianjiashilicheng;
	}

	/*
	 * 
	 * 夜间驾驶时间：夜间驾驶时间是满足夜间驾驶条件下一到多个夜间驾驶时间的总和
	 * 
	 * 首先要考虑的是一次夜间驾驶时间的计算实现：
	 * 
	 * 计算一次夜间驾驶时间
	 * 
	 * 假设一次里程最大持续时间小于20小时，当行驶里程跨越两天时，需以0点为界一分为二
	 * 一天的时间被日出日落时间分为三个区间：[0点，日出），[日出，日落），[日落，0点） 行驶里程按照排列组合在这三个区间中有6种情况：
	 * 
	 * 1.开始时间位于第一区间 1.1 结束时间位于第一区间：夜间行驶时间 = 结束时间 - 开始时间 1.2 结束时间位于第二区间：夜间行驶时间 =
	 * 日出时间 - 开始时间 1.3 结束时间位于第三区间：夜间行驶时间 = 日出时间 - 开始时间 + 结束时间 - 日落时间
	 * 
	 * 2.开始时间位于第二区间 2.1 结束时间位于第二区间：夜间行驶时间 = 0 2.2 结束时间位于第三区间：夜间行驶时间 = 结束时间 -
	 * 日落时间
	 * 
	 * 3.开始时间位于第三区间 3.1 结束时间位于第三区间：夜间行驶时间 = 结束时间 - 开始时间
	 * 
	 * 综上，计算一次夜间行驶时间需要：开始时间、结束时间、日出时间、日落时间
	 * 
	 * 在此基础上，将本次计算获得的夜间驾驶时间进行累加：夜间驾驶时间 = 夜间驾驶时间 + 本次求得的夜间驾驶时间
	 */
	private Long getNightDrivingInterval(TripData tripData) {
		
		Long yejianjiashishijian = 0L;
		// 开始时间
		Date kaishishijian = tripData.getKaishishijian();
		// 结束时间
		Date jieshushijian = tripData.getJieshushijian();

		// 日出时间
		Date sunRiseTimeOfTheDay = tripData.getSunRiseTimeOfTheDay();
		// 日落时间
		Date sunSetTimeOfTheDay = tripData.getSunSetTimeOfTheDay();

		// 1.开始时间位于第一区间
		if (kaishishijian.before(sunRiseTimeOfTheDay)) {
			// 1.1 结束时间位于第一区间：夜间行驶时间 = 结束时间 - 开始时间
			if (jieshushijian.before(sunRiseTimeOfTheDay)) {
				yejianjiashishijian = DateUtil.dateDiff(jieshushijian, kaishishijian);
			}
			// 1.2 结束时间位于第二区间：夜间行驶时间 = 日出时间 - 开始时间
			if ((jieshushijian.equals(sunRiseTimeOfTheDay) || jieshushijian
					.after(sunRiseTimeOfTheDay))
					&& jieshushijian.before(sunSetTimeOfTheDay)) {
				yejianjiashishijian = DateUtil
						.dateDiff(sunRiseTimeOfTheDay, kaishishijian);
			}
			// 1.3 结束时间位于第三区间：夜间行驶时间 = 日出时间 - 开始时间 + 结束时间 - 日落时间
			if (jieshushijian.equals(sunSetTimeOfTheDay)
					|| jieshushijian.after(sunSetTimeOfTheDay)) {
				yejianjiashishijian = DateUtil
						.dateDiff(sunRiseTimeOfTheDay, kaishishijian)
						+ DateUtil.dateDiff(jieshushijian, sunSetTimeOfTheDay);
			}
		}
		// 2.开始时间位于第二区间
		if ((kaishishijian.equals(sunRiseTimeOfTheDay) || kaishishijian
				.after(sunRiseTimeOfTheDay))
				&& kaishishijian.before(sunSetTimeOfTheDay)) {
			// 2.1 结束时间位于第二区间：夜间行驶时间 = 0
			if ((jieshushijian.equals(sunRiseTimeOfTheDay) || jieshushijian
					.after(sunRiseTimeOfTheDay))
					&& jieshushijian.before(sunSetTimeOfTheDay)) {
				yejianjiashishijian = 0L;
			}
			// 2.2 结束时间位于第三区间：夜间行驶时间 = 结束时间 - 日落时间
			if (jieshushijian.equals(sunSetTimeOfTheDay)
					|| jieshushijian.after(sunSetTimeOfTheDay)) {
				yejianjiashishijian = DateUtil.dateDiff(jieshushijian, sunSetTimeOfTheDay);
			}
		}
		// 3.开始时间位于第三区间
		if (kaishishijian.equals(sunSetTimeOfTheDay)
				|| kaishishijian.after(sunSetTimeOfTheDay)) {
			// 3.1 结束时间位于第三区间：夜间行驶时间 = 结束时间 - 开始时间
			yejianjiashishijian = DateUtil.dateDiff(jieshushijian, kaishishijian);
		}

		return yejianjiashishijian;
	}

	private Double getLateralAccelerationStandardDeviation(TripData tripData) {
		Double zonghengxiangjiasudupingfang = tripData
				.getZonghengxiangjiasudupingfang();
		Double hengxiangjiasudupingjunzhi = tripData
				.getHengxiangjiasudupingjunzhi();
		Long youxiaodeshujuliang = tripData.getYouxiaodeshujuliang();
		if (youxiaodeshujuliang == 0) {
			return 0.0;
		}
		return MathUtil.calcStandardDeviation(zonghengxiangjiasudupingfang, hengxiangjiasudupingjunzhi, youxiaodeshujuliang);
	}

	private double getTotalLateralAccelerationSquare(TripData tripData,
			Double hengxiangjiasudu) {
		Double zonghengxiangjiasudupingfang = tripData
				.getZonghengxiangjiasudupingfang();
		return zonghengxiangjiasudupingfang + Math.pow(hengxiangjiasudu, 2);
	}

	private Double getAvgLateralAcceleration(TripData tripData) {
		Double zonghengxiangjiasudu = tripData.getZonghengxiangjiasudu();
		Long youxiaoshujuliang = tripData.getYouxiaodeshujuliang();
		if (youxiaoshujuliang == 0) {
			return 0.0;
		}
		return zonghengxiangjiasudu / youxiaoshujuliang;
	}
	
	/**
	 * 
	 * 急加速：一次急加速是指加速度大于1.5的持续加速状态，一段时间内加速度如果连续大于
	 * 1.5代表一次急加速，因此急加速实际上是一个过程，捕获急加速的关键是捕获开始和结束
	 * 
	 * 使用一个急加速标志作为判断车辆是否处于急加速状态的依据结合加速度就可以确定急加速的开始和结束：
	 * 
	 * 当所得上次行程数据中的急加速标志为false，行车数据中的加速度大于1.5代表汽车进入急加速状态
	 * 当所得上次行程数据中的急加速标志为true，行车数据中的加速度小于等于1.5时代表汽车退出急加速状态
	 * 
	 * 急加速次数是行程中急加速的次数累计，可以选择在急加速开始或结束两个时间点进行计数，
	 * 考虑到现实中车祸对统计结果的影响，本方法选择在急加速开始阶段进行计数
	 * 
	 * 综上，计算急加速次数需要的数据是：急加速次数、加速度、急加速标志
	 * 
	 * @param stdData
	 * @param tripData
	 * @return
	 */
	private Integer getRapidAccelerationCnt(VehicleStandardData stdData,
			TripData tripData) {
		// 急加速次数
		Integer jijiasucishu = tripData.getJijiasucishu();
		// 加速度
		Double longAcceleration = stdData.getLongAcceleration();
		// 车速
		Double vSpeed = stdData.getVehicleSpeed();
		// 急加速标志
		Boolean rapidAccFlag = tripData.getRapidAccFlag();
		
		// 当所得上次行程数据中的急加速标志为false
		if (rapidAccFlag == false) {
			// 行车数据中的加速度大于1.5代表汽车进入急加速状态
			if (longAcceleration > 1.5 && vSpeed > 21.6) {
				tripData.setRapidAccFlag(true);
				jijiasucishu = jijiasucishu + 1;
			}
		}
		
		// 当所得上次行程数据中的急加速标志为true
		if (rapidAccFlag ==  true) {
			// 行车数据中的加速度小于等于1.5时代表汽车退出急加速状态
			if (!(longAcceleration > 1.5 && vSpeed > 21.6)) {
				tripData.setRapidAccFlag(false);
			}
			
			/*
			 * 2015-5-22 当前加速度大于1.5，且前后两条行车数据的时间戳间隔大于1秒
			 * 说明当前数据和前一数据在逻辑上是连续的，但是在时间上不连续，看做是一个新
			 * 急加速阶段的开始，急加速次数+1
			 */
			// 当前记录产生时间
			Date thisTime = tripData.getRecordTimestamp();
			// 上次记录产生时间
			Date lastTime = getLastRecordTimestampByVIN(tripData.getVin());
			// 计算时间间隔
			Long interval = DateUtil.dateDiff(thisTime, lastTime);
			
			if ((interval > 1000) && ((longAcceleration > 1.5 && vSpeed > 21.6))) {
				jijiasucishu = jijiasucishu + 1;
			}
		}
		
		return jijiasucishu;
	}
	
	/**
	 * 
	 * 急减速：一次急减速是指加速度小于-0.8的持续减速状态，一段时间内加速度如果连续小于
	 * -0.8代表一次急减速，因此急减速实际上是一个过程，捕获急减速的关键是捕获开始和结束
	 * 
	 * 使用一个急减速标志作为判断车辆是否处于急减速状态的依据结合加速度就可以确定急减速的开始和结束：
	 * 
	 * 当所得上次行程数据中的急减速标志为false，行车数据中的加速度小于-0.8代表汽车进入急减速状态
	 * 当所得上次行程数据中的急减速标志为true，行车数据中的加速度大于等于-0.8时代表汽车退出急减速状态
	 * 
	 * 急减速次数是行程中急减速的次数累计，可以选择在急减速开始或结束两个时间点进行计数，
	 * 考虑到现实中车祸对统计结果的影响，本方法选择在急减速开始阶段进行计数
	 * 
	 * 综上，计算急减速次数需要的数据是：急减速次数、加速度、急减速标志
	 * 
	 * @param stdData
	 * @param tripData
	 * @return
	 */
	private Integer getRapidDecelerationCnt(VehicleStandardData stdData,
			TripData tripData) {
		// 急减速次数
		Integer jijiansucishu = tripData.getJijiansucishu();
		// 加速度
		Double longAcceleration = stdData.getLongAcceleration();
		// 车速
		Double vSpeed = stdData.getVehicleSpeed();
		// 急减速标志
		Boolean rapidDccFlag = tripData.getRapidDccFlag();
		
		// 当所得上次行程数据中的急减速标志为false
		if (rapidDccFlag == false) {
			// 行车数据中的加速度小于-0.8代表汽车进入急减速状态
			if (longAcceleration < -2.3 && vSpeed > 10) {
				tripData.setRapidDccFlag(true);
				jijiansucishu = jijiansucishu + 1;
			}
		}
		
		// 当所得上次行程数据中的急减速标志为true
		if (rapidDccFlag == true) {
			// 行车数据中的加速度大于等于-0.8时代表汽车退出急减速状态
			if (!(longAcceleration < -2.3 && vSpeed > 10)) {
				tripData.setRapidDccFlag(false);
			}
			
			/*
			 * 2015-5-22 当前加速度小于-0.8，且前后两条行车数据的时间戳间隔大于1秒
			 * 说明当前数据和前一数据在逻辑上是连续的，但是在时间上不连续，看做是一个新
			 * 急减速阶段的开始，急减速次数+1
			 */
			// 当前记录产生时间
			Date thisTime = tripData.getRecordTimestamp();
			// 上次记录产生时间
			Date lastTime = getLastRecordTimestampByVIN(tripData.getVin());
			// 计算时间间隔
			Long interval = DateUtil.dateDiff(thisTime, lastTime);
			
			if ((interval > 1000) && (longAcceleration < -2.3 && vSpeed > 10)) {
				jijiansucishu = jijiansucishu + 1;
			}
		}
		return jijiansucishu;
	}

//	/**
//	 * 
//	 * 急转弯：一次急转弯是指横向加速度持续大于0.8的一段行车状态，计算急转弯次数的关键是捕获急转弯的开始和结束
//	 * 
//	 * 结合急转弯标志和横向加速度两个变量可以获得急转弯的开始和结束：
//	 * 
//	 * 当所得上次行程数据中的急转弯标志为false，行车数据中的横向加速度大于0.8代表汽车进入急转弯状态
//	 * 当所得上次行程数据中的急转弯标志为true，行车数据中的横向加速度小于等于0.8代表汽车退出急转弯状态
//	 * 
//	 * 急转弯次数是行程中急转弯次数累计，可以选择在急转弯开始或结束两个时间点进行计数，
//	 * 考虑到现实中车祸对统计结果的影响，本方法选择在急转弯开始阶段进行计数
//	 * 
//	 * 综上，计算急减速次数需要的数据是：急转弯次数、横向加速度、急转弯标志
//	 * 
//	 * @param tripData
//	 * @param hengxiangjiasudu
//	 * 
//	 * @return
//	 */
//	private Integer getSharpTurnCnt(TripData tripData, Double hengxiangjiasudu) {
//		// 急转弯次数
//		Integer jizhuanwancishu = tripData.getJizhuanwancishu();
//		// 横向加速度 hengxiangjiasudu
//		// 急转弯标志
//		Boolean sharpTurnFlag = tripData.getSharpTurnFlag();
//		
//		// 当所得上次行程数据中的急转弯标志为false
//		if (sharpTurnFlag == false) {
//			// 行车数据中的横向加速度大于0.8代表汽车进入急转弯状态
//			if (hengxiangjiasudu > 0.8) {
//				tripData.setSharpTurnFlag(true);
//				jizhuanwancishu = jizhuanwancishu + 1;
//			}
//		}
//		// 当所得上次行程数据中的急转弯标志为true
//		if (sharpTurnFlag == true) {
//			// 行车数据中的横向加速度小于等于0.8代表汽车退出急转弯状态
//			if (hengxiangjiasudu <= 0.8) {
//				tripData.setSharpTurnFlag(false);
//			}
//			
//			/*
//			 * 2015-5-22 当前横向加速度大于0.8，且前后两条行车数据的时间戳间隔大于1秒
//			 * 说明当前数据和前一数据在逻辑上是连续的，但是在时间上不连续，看做是一个新
//			 * 急转弯阶段的开始，急转弯次数+1
//			 */
//			// 当前记录产生时间
//			Date thisTime = tripData.getRecordTimestamp();
//			// 上次记录产生时间
//			Date lastTime = getLastRecordTimestampByVIN(tripData.getVin());
//			// 计算时间间隔
//			Long interval = DateUtil.dateDiff(thisTime, lastTime);
//			
//			if ((interval > 1000) && (hengxiangjiasudu > 0.8)) {
//				jizhuanwancishu = jizhuanwancishu + 1;
//			}
//			
//		}
//		return jizhuanwancishu;
//	}
	
	/**
	 * 
	 * 急转弯次数：车速 < 2 并且 发动机转速 > 500 持续时长3秒以上，期间横向加速度介于(3.5, 20)持续时长大于1秒计做一次急转弯
	 * 
	 * 简化算法：横向加速度大于3.5，持续时长大于1秒
	 * 
	 * @param tripData
	 * @param hengxiangjiasudu
	 * @return
	 */
	private Integer getSharpTurnCnt(TripData tripData, Double hengxiangjiasudu) {
		// 急转弯次数
		Integer jizhuanwancishu = tripData.getJizhuanwancishu();
		// 横向加速度 hengxiangjiasudu
		// 急转弯标志
		Boolean sharpTurnFlag = tripData.getSharpTurnFlag();
		
		// 当所得上次行程数据中的急转弯标志为false
		if (sharpTurnFlag == false) {
			// 行车数据中的横向加速度符合条件，车辆进入急转弯状态，记录横向加速度开始时间
			if (hengxiangjiasudu > 3.5 && hengxiangjiasudu < 20) {
				tripData.setSharpTurnFlag(true);
				tripData.setSharpTurnStartTime(tripData.getRecordTimestamp());
			}
		}
		// 当所得上次行程数据中的急转弯标志为true
		if (sharpTurnFlag == true) {
			// 行车数据中的横向加速度不满足条件时候，脱离急转弯状态
			if (hengxiangjiasudu <= 3.5 || hengxiangjiasudu >= 20) {
				tripData.setSharpTurnFlag(false);
			}
			
			// 当前记录产生时间
			Date thisTime = tripData.getRecordTimestamp();
			// 计算时间间隔
			Long interval = DateUtil.dateDiff(tripData.getSharpTurnStartTime(), thisTime);
			// 当急转弯状态时长超过1秒，急转弯次数+1
			if (interval > 1000) {
				jizhuanwancishu = jizhuanwancishu + 1;
			}
			
		}
		return jizhuanwancishu;
	}
	
	private Double getDecelerationStandardDeviation(TripData tripData) {
		Double zongjiansudupingfang = tripData.getZongjiansudupingfang();
		Double jiansudupingjunzhi = tripData.getJiansudupingjunzhi();
		Integer jiansucishu = tripData.getJiansucishu();
		if (jiansucishu == 0) {
			return 0.0;
		}
		return MathUtil.calcStandardDeviation(zongjiansudupingfang, jiansudupingjunzhi, jiansucishu) ;
	}

	private Double getTotalSquareDeceleration(VehicleStandardData stdData,
			TripData tripData) {
		Double longAcceleration = stdData.getLongAcceleration();
		Double zongjiansudupingfang = tripData.getZongjiansudupingfang();
		if (longAcceleration < 0) {
			zongjiansudupingfang = zongjiansudupingfang
					+ Math.pow(longAcceleration, 2);
		}
		return zongjiansudupingfang;
	}

	private Double getAvgDeceleration(TripData tripData) {
		Integer jiansucishu = tripData.getJiansucishu();
		if (jiansucishu == 0) {
			return 0.0;
		}
		Double avgDeceleration = tripData.getZongjiansudu()
				/ jiansucishu;
		return avgDeceleration;
	}

	private Double getTotalDeceleration(VehicleStandardData stdData,
			TripData tripData) {
		Double longAcceleration = stdData.getLongAcceleration();
		Double zongjiansudu = tripData.getZongjiansudu();
		if (longAcceleration < 0) {
			zongjiansudu = zongjiansudu + longAcceleration;
		}
		return zongjiansudu;
	}

	private Integer getDecelerationCnt(VehicleStandardData stdData,
			TripData tripData) {
		Double longAcceleration = stdData.getLongAcceleration();
		Integer jiansuducishu = tripData.getJiansucishu();
		if (longAcceleration < 0) {
			jiansuducishu++;
		}
		return jiansuducishu;
	}

	private double getAccelerationStandardDeviation(TripData tripData) {
		Double zongjiasudupingfang = tripData.getZongjiasudupingfang();
		Double jiasudupingjunzhi = tripData.getJiasudupingjunzhi();
		Integer jiasucishu = tripData.getJiasucishu();
		if (jiasucishu == 0) {
			return 0.0;
		}
		return MathUtil.calcStandardDeviation(zongjiasudupingfang, jiasudupingjunzhi, jiasucishu);
	}

	private Double getTotalSquareAcceleration(VehicleStandardData stdData,
			TripData tripData) {
		Double longAcceleration = stdData.getLongAcceleration();
		Double zongjiasudupingfang = tripData.getZongjiasudupingfang();
		if (longAcceleration > 0) {
			zongjiasudupingfang = zongjiasudupingfang
					+ Math.pow(longAcceleration, 2);
		}
		return zongjiasudupingfang;
	}

	private Double getTotalAcceleration(VehicleStandardData stdData,
			TripData tripData) {
		Double longAcceleration = stdData.getLongAcceleration();
		Double zongjiasudu = tripData.getZongjiasudu();
		if (longAcceleration > 0) {
			zongjiasudu = zongjiasudu + longAcceleration;
		}
		return zongjiasudu;
	}

	private Integer getAccelerationCnt(VehicleStandardData stdData,
			TripData tripData) {
		Double longAcceleration = stdData.getLongAcceleration();
		Integer jiasuducishu = tripData.getJiasucishu();
		if (longAcceleration > 0) {
			jiasuducishu++;
		}
		return jiasuducishu;
	}

	private Double getAvgAcceleration(TripData tripData) {
		Integer jiasucishu = tripData.getJiasucishu();
		if (jiasucishu == 0) {
			return 0.0;
		}
		Double avgAcceleration = tripData.getZongjiasudu()
				/ jiasucishu;
		return avgAcceleration;
	}

	private Double getDataLossRate(TripData tripData) {
		Double shujudiushilv = 0.0;
		
		Long tripshijianchangdu = tripData.getTripshijianchangdu();
		if (tripshijianchangdu == null) {
			return 0.0;
		}
		if (tripshijianchangdu == 0) {
			return 0.0;
		}
		Long youxiaodeshujuliang = tripData.getYouxiaodeshujuliang();
		if (youxiaodeshujuliang == null) {
			return 0.0;
		}
		shujudiushilv = Double.valueOf((tripshijianchangdu - youxiaodeshujuliang)
				/ tripshijianchangdu);
		return shujudiushilv;
	}

	/**
	 * 计算行程中车速非0的发动机转速平均值
	 * @param tripData
	 * @return
	 */
	private double getAvgEngineSpeed(TripData tripData) {
		Integer engineSpeedCnt = tripData.getEngineSpeedCnt();
		if (engineSpeedCnt == 0) {
			return 0.0;
		}
		return tripData.getZongfadongjizhuansu()
				/ engineSpeedCnt;
	}

	private double getAvgSpeed(TripData tripData) {
		Integer speedCnt = tripData.getSpeedCnt();
		
		if (speedCnt == 0) {
			return 0.0;
		}
		return tripData.getZongsudu() / speedCnt;
	}

	private Double getAVGTP_bright(VehicleStandardData stdData,
			TripData tripData) {
		Double pingjuntaiya_houyou = tripData.getZongtaiya_qianyou()
				/ tripData.getYouxiaodeshujuliang();
		return pingjuntaiya_houyou;
	}

	private Double getAVGTP_bleft(VehicleStandardData stdData, TripData tripData) {
		Double pingjuntaiya_houzuo;
		pingjuntaiya_houzuo = tripData.getZongtaiya_qianyou()
				/ tripData.getYouxiaodeshujuliang();
		return pingjuntaiya_houzuo;
	}

	private Double getAVGTP_fright(VehicleStandardData stdData,
			TripData tripData) {
		Double pingjuntaiya_qianyou = tripData.getZongtaiya_qianyou()
				/ tripData.getYouxiaodeshujuliang();
		return pingjuntaiya_qianyou;
	}

	private Double getAVGTP_fleft(VehicleStandardData stdData, TripData tripData) {
		Double pingjuntaiya_qianzuo = tripData.getZongtaiya_qianyou()
				/ tripData.getYouxiaodeshujuliang();
		return pingjuntaiya_qianzuo;
	}

	private double getCarbonDioxideEmissions(VehicleStandardData stdData, TripData tripData) {
		// 获得二氧化碳排放量
		Double emisCO2 = tripData.getEryanghuatanpaifangliang();
		// 计算本次顺时二氧化碳排放量 EmisCO2=sum(1.0 * 顺时油耗 / 100.0 * 车速) / 3600.0 * 720.0 * 2.99)
		Double e = 1.0 * stdData.getInstantConsum() / 100.0 * stdData.getVehicleSpeed() / 3600.0 * 720.0 * 2.99;
		// 获得合计
		emisCO2 = e + emisCO2;
		// 返回结果
		return emisCO2;
	}

	private Double getAvgFuelConsumption(TripData tripData) {
		Double pingjunyouhao = tripData.getZongyouhao()
				/ tripData.getYouxiaodeshujuliang();
		return pingjunyouhao;
	}

	/**
	 * 
	 * 怠速时间长度：VehicleSpeed < 2 累计10秒，开始统计怠速时间，之后1秒怠速时间为11秒
	 * 
	 * 分析上述说明可知，计算怠速时长的关键是获得怠速开始时的时间和怠速结束时的时间，根据时 长大小决定是否加入怠速统计。两种时间点的判断办法如下：
	 * 
	 * 1.怠速开始：行驶速度小于2时，如果取得的怠速标志为false，说明之前的行驶过程都是非怠速
	 * 状态，当前时刻是前一次怠速行驶后的第一次车速小于2的时点，是本次怠速行驶的起点
	 * 
	 * 怠速开始时做两件事： 1.1 记录怠速开始时间 1.2 将怠速标志改为true
	 * 
	 * 2.怠速结束：行驶速度大于2时，如果取得的怠速标志为true，说明之前的行驶过程都是怠速状
	 * 态，当前时刻是本次怠速行驶过程中首次车速大于2的时点，是本次怠速行驶过程的终点
	 * 
	 * 怠速结束时做三件事： 1.计算本次怠速过程时长 = 怠速结束时间(当前行车数据产生时间) - 怠速开始时间
	 * 2.如果本次怠速过程时长大于10秒，将本次怠速时长累加:怠速时间长度 = 怠速时间长度 - 本次怠速过程时长 3.将怠速标志改为false
	 * 
	 * 综上，计算怠速所需的数据为： 怠速时间长度、行驶速度、怠速标志、记录产生时间、怠速开始时间
	 */
	private Long getIdleInterval(VehicleStandardData stdData, TripData tripData) {
		// 怠速时间长度
		Long daisushijianchangdu = tripData.getDaisushijianchangdu();
		// 行驶速度
		Double vehicleSpeed = stdData.getVehicleSpeed();
		// 怠速标志
		Boolean idleFlag = tripData.getIdleFlag();
		Double engineSpeed = stdData.getEngineSpeed();
		// 记录产生时间
		Date recordTimestamp = stdData.getRecordTimestamp();

		/**
		 * 添加发动机转速大于500的条件
		 */
		if (vehicleSpeed < 2 && engineSpeed > 500) {
			if (idleFlag == false) {
				// 1.怠速开始：行驶速度小于2时，如果取得的怠速标志为false，说明之前的行驶过程都是非怠速
				// 状态，当前时刻是前一次怠速行驶后的第一次车速小于2的时点，是本次怠速行驶的起点
				// 怠速开始时做两件事：
				// 1.1 记录怠速开始时间
				// 1.2 将怠速标志改为true
				tripData.setDaisukaishishijian(recordTimestamp);
				tripData.setIdleFlag(true);
			}
		} else {
			if (idleFlag == true) {
				// 2.怠速结束：行驶速度大于2时，如果取得的当怠速标志为true，说明之前的行驶过程都是怠速状
				// 态，当前时刻是本次怠速行驶过程中首次车速大于2的时点，是本次怠速行驶过程的终点
				//
				// 怠速结束时做三件事：
				// 1.计算本次怠速过程时长 = 怠速结束时间(当前行车数据产生时间) - 怠速开始时间
				Date daisukaishishijian = tripData.getDaisukaishishijian();
				Long interval = DateUtil.dateDiff(recordTimestamp,
						daisukaishishijian);
				// 2.如果本次怠速过程时长大于10秒（10000毫秒），将本次怠速时长累加至tripData的怠速时间长度变量中
				/**
				 * 经过和观致python程序比较，根本没有10秒逻辑，修改之
				 */
				if (interval > 0) {
					daisushijianchangdu = daisushijianchangdu + interval;
				}
				// 3.将怠速标志改为false
				tripData.setIdleFlag(false);
			}
		}
		return daisushijianchangdu;
	}

	private LocationInformation getLocationInformation(
			VehicleStandardData stdData) {
		Double longitude = stdData.getLongitude();
		Double latitude = stdData.getLatitude();
		LocationInformation locationInformation = new LocationInformation(
				longitude, latitude);
		return locationInformation;
	}

	private Double calcTripLength(VehicleStandardData stdData, TripData tripData) {

		Double endMileage = stdData.getKilometreMileage();
		Double startMileage = tripData.getKaishilichengbiaodushu();

		return endMileage - startMileage;
	}

	/**
	 * ZeroAcc是一个修正值，当车辆维持某一特定状态长达60秒以上时需要此值修正计算
	 * 
	 * @param stdData
	 * @return
	 */
	private Double calcZeroAcc(VehicleStandardData stdData) {
		// 计算 ZeroAcc
		// ACC = -1.0 * LongAcceleration
		Double ACC = -1.0 * stdData.getLongAcceleration();

		// tmpACC = ACC[numpy.abs(VehicleSpeed) < 0.1]
		if (Math.abs(stdData.getVehicleSpeed()) < 0.1) {
			mv.add(ACC);
		}

		// ZeroAcc = scipy.stats.mode(tmpACC)[0] if tmpACC.size > 60 else 0.0
		if (mv.size() > 60) {
			try {
				return mv.getMode();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return 0.0;
	}

	public void declareOutputFields(OutputFieldsDeclarer declare) {
		declare.declare(new Fields("tripcalculatedata"));
	}

	@SuppressWarnings("rawtypes")
	public void prepare(Map stormConf, TopologyContext context,
			OutputCollector collector) {
		this.tripDataMap = new HashMap<String, TripData>();
		this.stdDataMap = new HashMap<String, VehicleStandardData>();
		this.mv = new ModeArrayList();
		this.statData = new StatData();
		this.collector = collector;
	}

	// 获取最大车速
	public Double getMaxSpeed(VehicleStandardData stdData, TripData tripData) {
		Double currentSpeed = stdData.getVehicleSpeed();
		Double maxSpeed = tripData.getZuidachesu();
		if (currentSpeed > maxSpeed) {
			return currentSpeed;
		} else {
			return maxSpeed;
		}
	}

	// 获取总油耗
	public Double getTotalConsum(VehicleStandardData stdData, TripData tripData) {
		Double instantConsum = stdData.getInstantConsum();
		Double zongyouhao = tripData.getZongyouhao();
		return zongyouhao + instantConsum;
	}

	// 最大发动机速度
	public Double getMaxEngine(VehicleStandardData stdData, TripData tripData) {
		Double zuidafadongjisudu = tripData.getZuidafadongjisudu();
		Double engineSpeed = stdData.getEngineSpeed();
		if (engineSpeed > zuidafadongjisudu) {
			return engineSpeed;
		} else {
			return zuidafadongjisudu;
		}
	}

	// 所有车速之和，用来求解平均车速 总车速除以传过来数据的次数
	public Double getTotalSpeed(VehicleStandardData stdData, TripData tripData) {
		Double zongsudu = tripData.getZongsudu();
		Double vehicleSpeed = stdData.getVehicleSpeed();
		return zongsudu + vehicleSpeed;
	}

	/**
	 *  总发动机转速，用来求解平均发动机转速 总发动机转速除以传过来数据的次数
	 *  注意：此方法只统计车速非0下的发动机转速
	 * @param stdData
	 * @param tripData
	 * @return
	 */
	public Double getTotalEngine(VehicleStandardData stdData, TripData tripData) {
		Double zongfadongjizhuansu = tripData.getZongfadongjizhuansu();
		Double engineSpeed = 0.0;
		if (stdData.getVehicleSpeed() > 0) {
			engineSpeed = stdData.getEngineSpeed();	
		}
		return zongfadongjizhuansu + engineSpeed;
	}
	
	public Integer getEngineSpeedCnt(VehicleStandardData stdData, TripData tripData) {
		Integer engineSpeedCnt = tripData.getEngineSpeedCnt();
		if (stdData.getVehicleSpeed() > 0) {
			engineSpeedCnt = engineSpeedCnt + 1;
		}
		return engineSpeedCnt;
	}

	/*
	 * 下面几个方法用来求各个轮子的总胎压 然后用来求各个轮子的平均胎压 一共是四个方法，代表四个轮子
	 */
	public Double getTotalTP_fleft(VehicleStandardData stdData,
			TripData tripData) { // 前左
		Double zongtaiya_qianzuo = tripData.getZongtaiya_qianzuo();
		Double flpressure = stdData.getFLPressure();
		return zongtaiya_qianzuo + flpressure;
	}

	public Double getTotalTP_fright(VehicleStandardData stdData,
			TripData tripData) { // 前右
		Double zongtaiya_qianzuo = tripData.getZongtaiya_qianzuo();
		Double frpressure = stdData.getFRPressure();
		return zongtaiya_qianzuo + frpressure;
	}

	public Double getTotalTP_bleft(VehicleStandardData stdData,
			TripData tripData) { // 后左
		Double zongtaiya_qianzuo = tripData.getZongtaiya_qianzuo();
		Double rlpressure = stdData.getRLPressure();
		return zongtaiya_qianzuo + rlpressure;
	}

	public Double getTotalTP_bright(VehicleStandardData stdData,
			TripData tripData) { // 后右
		Double zongtaiya_qianzuo = tripData.getZongtaiya_qianzuo();
		Double rrpressure = stdData.getRRPressure();
		return zongtaiya_qianzuo + rrpressure;
	}

	// 计算横向加速度的一些方法
	private Double getLateralAcceleration(VehicleStandardData stdData) // 横向加速度的算法
	{
		Double speed = stdData.getVehicleSpeed();
		Double steeringpos = stdData.getSteeringPos();
		Double hengxiangjiasudu = (speed / 3.6) * (speed / 3.6)
				* Math.abs(Math.sin(steeringpos / 515 * 32 * 3.14 / 180)) / 2.7;
		return hengxiangjiasudu;
	}

	// 记录每天处理的数据条数
	private Long getNumDataProcessed(StatData statData) {
		numDataProcessed = statData.getNumDataProcessed();
		if (DateUtil.getMilliSecond() == 0)
			numDataProcessed = 0;
		else
			numDataProcessed++;
		return numDataProcessed;
	}

	// 记录当前在线车辆数
	private Long getNumCarOnline(HashMap<String, TripData> hm) {
		Iterator<Entry<String, TripData>> iter = hm.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			TripData val = (TripData) entry.getValue(); // 获得TripData对象
			if (val.getTripflag() != TripData.END)
				numCarOnline++;
		}
		return numCarOnline;
	}

	public Double getTotalLateralAcceleration(TripData tripData,
			Double hengxiangjiasudu) {
		Double zonghengxiangjiasudu = tripData.getZonghengxiangjiasudu();
		return zonghengxiangjiasudu + hengxiangjiasudu;
	}

	public void cleanup() {

	}

}
